There's no need to keep a "FILE *" for the file being printed to in a
[obnox/wireshark/wip.git] / 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: packet-fcswils.c,v 1.8 2003/12/04 05:40:17 gram Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
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 #ifdef NEED_SNPRINTF_H
45 # include "snprintf.h"
46 #endif
47
48 #include <epan/packet.h>
49 #include <epan/conversation.h>
50 #include "etypes.h"
51 #include "packet-fc.h"
52 #include "packet-fcswils.h"
53
54 #define FC_SWILS_RPLY               0x0
55 #define FC_SWILS_REQ                0x1
56 #define FC_SWILS_RSCN_DEVENTRY_SIZE 20
57
58 /* Zone name has the structure:
59  * name_len (1 byte), rsvd (3 bytes), name (m bytes), fill (n bytes)
60  * name_len excludes the 4 initial bytes before the name
61  */
62 #define ZONENAME_LEN(x, y)  (tvb_get_guint8(x, y)+4)
63
64 /* Initialize the protocol and registered fields */
65 static int proto_fcswils               = -1;
66 static int hf_swils_opcode             = -1;
67 static int hf_swils_elp_rev            = -1;
68 static int hf_swils_elp_flags          = -1;
69 static int hf_swils_elp_r_a_tov        = -1;
70 static int hf_swils_elp_e_d_tov        = -1;
71 static int hf_swils_elp_req_epn        = -1;
72 static int hf_swils_elp_req_esn        = -1;
73 static int hf_swils_elp_clsf_svcp      = -1;
74 static int hf_swils_elp_clsf_rcvsz     = -1;
75 static int hf_swils_elp_clsf_conseq    = -1;
76 static int hf_swils_elp_clsf_e2e       = -1;
77 static int hf_swils_elp_clsf_openseq   = -1;
78 static int hf_swils_elp_cls1_svcp      = -1;
79 static int hf_swils_elp_cls1_rcvsz     = -1;
80 static int hf_swils_elp_cls2_svcp      = -1;
81 static int hf_swils_elp_cls2_rcvsz     = -1;
82 static int hf_swils_elp_cls3_svcp      = -1;
83 static int hf_swils_elp_cls3_rcvsz     = -1;
84 static int hf_swils_elp_isl_fc_mode    = -1;
85 static int hf_swils_elp_fcplen         = -1;
86 static int hf_swils_elp_b2bcredit      = -1;
87 static int hf_swils_elp_compat1        = -1;
88 static int hf_swils_elp_compat2        = -1;
89 static int hf_swils_elp_compat3        = -1;
90 static int hf_swils_elp_compat4        = -1;
91 static int hf_swils_efp_rec_type       = -1;
92 static int hf_swils_efp_dom_id         = -1;
93 static int hf_swils_efp_switch_name    = -1;
94 static int hf_swils_efp_mcast_grpno    = -1;
95 static int hf_swils_efp_alias_token    = -1;
96 static int hf_swils_efp_payload_len    = -1;
97 static int hf_swils_efp_pswitch_pri    = -1;
98 static int hf_swils_efp_pswitch_name   = -1;
99 static int hf_swils_dia_switch_name    = -1;
100 static int hf_swils_rdi_payload_len    = -1;
101 static int hf_swils_rdi_req_sname      = -1;
102 static int hf_swils_fspfh_cmd          = -1;
103 static int hf_swils_fspfh_rev          = -1;
104 static int hf_swils_fspfh_ar_num       = -1;
105 static int hf_swils_fspfh_auth_type    = -1;
106 static int hf_swils_fspfh_dom_id       = -1;
107 static int hf_swils_fspfh_auth         = -1;
108 static int hf_swils_hlo_options        = -1;
109 static int hf_swils_hlo_hloint         = -1;
110 static int hf_swils_hlo_deadint        = -1;
111 static int hf_swils_hlo_rcv_domid      = -1;
112 static int hf_swils_hlo_orig_pidx      = -1;
113 static int hf_swils_ldrec_linkid       = -1;
114 static int hf_swils_ldrec_out_pidx     = -1;
115 static int hf_swils_ldrec_nbr_pidx     = -1;
116 static int hf_swils_ldrec_link_type    = -1;
117 static int hf_swils_ldrec_link_cost    = -1;
118 static int hf_swils_lsrh_lsr_type      = -1;
119 static int hf_swils_lsrh_lsid          = -1;
120 static int hf_swils_lsrh_adv_domid     = -1;
121 static int hf_swils_lsrh_ls_incid      = -1;
122 static int hf_swils_esc_pdesc_vendorid = -1;
123 static int hf_swils_esc_swvendorid     = -1;
124 static int hf_swils_esc_protocolid     = -1;
125 static int hf_swils_rscn_evtype        = -1;
126 static int hf_swils_rscn_addrfmt       = -1;
127 static int hf_swils_rscn_detectfn      = -1;
128 static int hf_swils_rscn_affectedport  = -1;
129 static int hf_swils_rscn_portstate     = -1;
130 static int hf_swils_rscn_portid        = -1;
131 static int hf_swils_rscn_pwwn          = -1;
132 static int hf_swils_rscn_nwwn          = -1;
133 static int hf_swils_zone_activezonenm  = -1;
134 static int hf_swils_zone_objname       = -1;
135 static int hf_swils_zone_objtype       = -1;
136 static int hf_swils_zone_mbrtype       = -1;
137 static int hf_swils_zone_protocol      = -1;
138 static int hf_swils_zone_mbrid         = -1;
139 static int hf_swils_zone_status        = -1;
140 static int hf_swils_zone_reason        = -1;
141 static int hf_swils_aca_domainid       = -1;
142 static int hf_swils_sfc_opcode         = -1;
143 static int hf_swils_sfc_zonenm         = -1;
144 static int hf_swils_rjt                = -1;
145 static int hf_swils_rjtdet             = -1;
146 static int hf_swils_rjtvendor          = -1;
147 static int hf_swils_zone_mbrid_lun     = -1;
148
149 /* Initialize the subtree pointers */
150 static gint ett_fcswils             = -1;
151 static gint ett_fcswils_swacc       = -1;
152 static gint ett_fcswils_swrjt       = -1;
153 static gint ett_fcswils_elp         = -1;
154 static gint ett_fcswils_efp         = -1;
155 static gint ett_fcswils_efplist     = -1;
156 static gint ett_fcswils_dia         = -1;
157 static gint ett_fcswils_rdi         = -1;
158 static gint ett_fcswils_fspfhdr     = -1;
159 static gint ett_fcswils_hlo         = -1;
160 static gint ett_fcswils_lsrec       = -1;
161 static gint ett_fcswils_lsrechdr    = -1;
162 static gint ett_fcswils_ldrec       = -1;
163 static gint ett_fcswils_lsu         = -1;
164 static gint ett_fcswils_lsa         = -1;
165 static gint ett_fcswils_bf          = -1;
166 static gint ett_fcswils_rcf         = -1;
167 static gint ett_fcswils_rscn        = -1;
168 static gint ett_fcswils_rscn_dev    = -1;
169 static gint ett_fcswils_drlir       = -1;
170 static gint ett_fcswils_mr          = -1;
171 static gint ett_fcswils_zoneobjlist = -1;
172 static gint ett_fcswils_zoneobj     = -1;
173 static gint ett_fcswils_zonembr     = -1;
174 static gint ett_fcswils_aca         = -1;
175 static gint ett_fcswils_rca         = -1;
176 static gint ett_fcswils_sfc         = -1;
177 static gint ett_fcswils_ufc         = -1;
178 static gint ett_fcswils_esc         = -1;
179 static gint ett_fcswils_esc_pdesc   = -1;
180
181 static const value_string fc_swils_opcode_key_val[] = {
182     {FC_SWILS_SWRJT  , "SW_RJT"},
183     {FC_SWILS_SWACC  , "SW_ACC"},
184     {FC_SWILS_ELP    , "ELP"},
185     {FC_SWILS_EFP    , "EFP"},
186     {FC_SWILS_DIA    , "DIA"},
187     {FC_SWILS_RDI    , "RDI"},
188     {FC_SWILS_HLO    , "HLO"},
189     {FC_SWILS_LSU    , "LSU"},
190     {FC_SWILS_LSA    , "LSA"},
191     {FC_SWILS_BF     , "BF"},
192     {FC_SWILS_RCF    , "RCF"},
193     {FC_SWILS_RSCN   , "SW_RSCN"},
194     {FC_SWILS_DRLIR  , "DRLIR"},
195     {FC_SWILS_DSCN   , "DSCN"},
196     {FC_SWILS_LOOPD  , "LOOPD"},
197     {FC_SWILS_MR     , "MR"},
198     {FC_SWILS_ACA    , "ACA"},
199     {FC_SWILS_RCA    , "RCA"},
200     {FC_SWILS_SFC    , "SFC"},
201     {FC_SWILS_UFC    , "UFC"},
202     {FC_SWILS_ESC    , "ESC"},
203     {FC_SWILS_AUTH_ILS, "AUTH_ILS"},
204     {0, NULL},
205 };
206
207 static const value_string fc_swils_rjt_val [] = {
208     {FC_SWILS_RJT_INVCODE   , "Invalid Cmd Code"},
209     {FC_SWILS_RJT_INVVER    , "Invalid Revision"},
210     {FC_SWILS_RJT_LOGERR    , "Logical Error"},
211     {FC_SWILS_RJT_INVSIZE   , "Invalid Size"},
212     {FC_SWILS_RJT_LOGBSY    , "Logical Busy"},
213     {FC_SWILS_RJT_PROTERR   , "Protocol Error"},
214     {FC_SWILS_RJT_GENFAIL   , "Unable to Perform"},
215     {FC_SWILS_RJT_CMDNOTSUPP, "Unsupported Cmd"},
216     {FC_SWILS_RJT_VENDUNIQ  , "Vendor Unique Err"},
217     {0, NULL},
218 };
219
220 static const value_string fc_swils_deterr_val [] = {
221     {FC_SWILS_RJT_NODET ,      "No Additional Details"},
222     {FC_SWILS_RJT_CLSF_ERR ,   "Class F Svc Param Err"},
223     {FC_SWILS_RJT_CLSN_ERR ,   "Class N Svc Param Err"},
224     {FC_SWILS_RJT_INVFC_CODE , "Unknown Flow Ctrl Code"},
225     {FC_SWILS_RJT_INVFC_PARM , "Invalid Flow Ctrl Parm"},
226     {FC_SWILS_RJT_INV_PNAME ,  "Invalid Port Name"},
227     {FC_SWILS_RJT_INV_SNAME ,  "Invalid Switch Name"},
228     {FC_SWILS_RJT_TOV_MSMTCH , "R_A_/E_D_TOV Mismatch"},
229     {FC_SWILS_RJT_INV_DIDLST,  "Invalid Domain ID List"},
230     {FC_SWILS_RJT_CMD_INPROG , "Cmd Already in Progress"},
231     {FC_SWILS_RJT_OORSRC ,     "Insufficient Resources"},
232     {FC_SWILS_RJT_NO_DID ,     "Domain ID Unavailable"},
233     {FC_SWILS_RJT_INV_DID,     "Invalid Domain ID"},
234     {FC_SWILS_RJT_NO_REQ ,     "Request Not Supported"},
235     {FC_SWILS_RJT_NOLNK_PARM , "Link Parm Not Estd."},
236     {FC_SWILS_RJT_NO_REQDID ,  "Group of Domain IDs Unavail"},
237     {FC_SWILS_RJT_EP_ISOL ,    "E_Port Isolated"},
238     {0, NULL}
239 };
240
241 static const value_string fcswils_elp_fc_val[] = {
242     {FC_SWILS_ELP_FC_VENDOR, "Vendor Unique"},
243     {FC_SWILS_ELP_FC_RRDY,   "R_RDY Flow Ctrl"},
244     {0, NULL},
245 };
246
247 static const value_string fcswils_rectype_val[] = {
248     {FC_SWILS_LRECTYPE_DOMAIN, "Domain ID List Rec"},
249     {FC_SWILS_LRECTYPE_MCAST, "Multicast ID List Rec"},
250     {0, NULL},
251 };
252
253 static const value_string fc_swils_link_type_val[] = {
254     {0x01, "P2P Link"},
255     {0xF0, "Vendor Specific"},
256     {0xF1, "Vendor Specific"},
257     {0xF2, "Vendor Specific"},
258     {0xF3, "Vendor Specific"},
259     {0xF4, "Vendor Specific"},
260     {0xF5, "Vendor Specific"},
261     {0xF6, "Vendor Specific"},
262     {0xF7, "Vendor Specific"},
263     {0xF8, "Vendor Specific"},
264     {0xF9, "Vendor Specific"},
265     {0xFA, "Vendor Specific"},
266     {0xFB, "Vendor Specific"},
267     {0xFC, "Vendor Specific"},
268     {0xFD, "Vendor Specific"},
269     {0xFE, "Vendor Specific"},
270     {0xFF, "Vendor Specific"},
271     {0, NULL},
272 };
273
274 static const value_string fc_swils_fspf_linkrec_val[] = {
275     {FC_SWILS_LSR_SLR, "Switch Link Record"},
276     {FC_SWILS_LSR_ARS, "AR Summary Record"},
277     {0, NULL},
278 };
279
280 static const value_string fc_swils_fspf_lsrflags_val[] = {
281     {0x0, "LSR is for a Topology Update"},
282     {0x1, "LSR is for Initial DB Sync | Not the last seq in DB sync"},
283     {0x2, "Last Seq in DB Sync. LSU has no LSRs"},
284     {0x3, "LSR is for Initial DB Sync | Last Seq in DB Sync"},
285     {0, NULL},
286 };
287
288 static const value_string fc_swils_rscn_portstate_val[] = {
289     {0, "No Additional Info"},
290     {1, "Port is online"},
291     {2, "Port is offline"},
292     {0, NULL},
293 };
294
295 static const value_string fc_swils_rscn_addrfmt_val[] = {
296     {0, "Port Addr Format"},
297     {1, "Area Addr Format"},
298     {2, "Domain Addr Format"},
299     {3, "Fabric Addr Format"},
300     {0, NULL},
301 };
302
303 static const value_string fc_swils_rscn_detectfn_val[] = {
304     {1, "Fabric Detected"},
305     {2, "N_Port Detected"},
306     {0, NULL},
307 };
308
309 static const value_string fc_swils_esc_protocol_val[] = {
310     {0, "Reserved"},
311     {1, "FSPF-Backbone Protocol"},
312     {2, "FSPF Protocol"},
313     {0, NULL},
314 };
315
316 static const value_string fc_swils_zoneobj_type_val[] = {
317     {0, "Reserved"},
318     {FC_SWILS_ZONEOBJ_ZONESET  , "Zone Set"},
319     {FC_SWILS_ZONEOBJ_ZONE     , "Zone"},
320     {FC_SWILS_ZONEOBJ_ZONEALIAS, "Zone Alias"},
321     {0, NULL},
322 };
323
324 const value_string fc_swils_zonembr_type_val[] = {
325     {0, "Reserved"},
326     {FC_SWILS_ZONEMBR_WWN, "WWN"},
327     {FC_SWILS_ZONEMBR_DP, "Domain/Physical Port (0x00ddpppp)"},
328     {FC_SWILS_ZONEMBR_FCID, "FC Address"},
329     {FC_SWILS_ZONEMBR_ALIAS, "Zone Alias"},
330     {FC_SWILS_ZONEMBR_WWN_LUN, "WWN+LUN"},
331     {FC_SWILS_ZONEMBR_DP_LUN, "Domain/Physical Port+LUN"},
332     {FC_SWILS_ZONEMBR_FCID_LUN, "FCID+LUN"},
333     {0, NULL},
334 };
335
336 static const value_string fc_swils_mr_rsp_val[] = {
337     {0, "Successful"},
338     {1, "Fabric Busy"},
339     {2, "Failed"},
340     {0, NULL},
341 };
342
343 static const value_string fc_swils_mr_reason_val[] = {
344     {0x0, "No Reason"},
345     {0x1, "Invalid Data Length"},
346     {0x2, "Unsupported Command"},
347     {0x3, "Reserved"},
348     {0x4, "Not Authorized"},
349     {0x5, "Invalid Request"},
350     {0x6, "Fabric Changing"},
351     {0x7, "Update Not Staged"},
352     {0x8, "Invalid Zone Set Format"},
353     {0x9, "Invalid Data"},
354     {0xA, "Cannot Merge"},
355     {0, NULL},
356 };
357
358 static const value_string fc_swils_sfc_op_val[] = {
359     {0, "Reserved"},
360     {1, "Reserved"},
361     {2, "Reserved"},
362     {3, "Activate Zone Set"},
363     {4, "Deactivate Zone Set"},
364     {0, NULL},
365 };
366
367 typedef struct _zonename {
368     guint32 namelen:8,
369             rsvd:24;
370     gchar *name;
371     gchar *pad;
372 } zonename_t;
373
374 typedef struct _fcswils_conv_key {
375     guint32 conv_idx;
376 } fcswils_conv_key_t;
377
378 typedef struct _fcswils_conv_data {
379     guint32 opcode;
380 } fcswils_conv_data_t;
381
382 GHashTable *fcswils_req_hash = NULL;
383 GMemChunk *fcswils_req_keys = NULL;
384 GMemChunk *fcswils_req_vals = NULL;
385 guint32 fcswils_init_count = 25;
386
387 static dissector_handle_t data_handle, fcsp_handle;
388
389 static gint get_zoneobj_len (tvbuff_t *tvb, gint offset);
390
391 /*
392  * Hash Functions
393  */
394 static gint
395 fcswils_equal(gconstpointer v, gconstpointer w)
396 {
397   fcswils_conv_key_t *v1 = (fcswils_conv_key_t *)v;
398   fcswils_conv_key_t *v2 = (fcswils_conv_key_t *)w;
399
400   return (v1->conv_idx == v2->conv_idx);
401 }
402
403 static guint
404 fcswils_hash (gconstpointer v)
405 {
406         fcswils_conv_key_t *key = (fcswils_conv_key_t *)v;
407         guint val;
408
409         val = key->conv_idx;
410
411         return val;
412 }
413
414 /*
415  * Protocol initialization
416  */
417 static void
418 fcswils_init_protocol(void)
419 {
420         if (fcswils_req_keys)
421             g_mem_chunk_destroy (fcswils_req_keys);
422         if (fcswils_req_vals)
423             g_mem_chunk_destroy (fcswils_req_vals);
424         if (fcswils_req_hash)
425             g_hash_table_destroy (fcswils_req_hash);
426
427         fcswils_req_hash = g_hash_table_new(fcswils_hash, fcswils_equal);
428         fcswils_req_keys = g_mem_chunk_new("fcswils_req_keys",
429                                            sizeof(fcswils_conv_key_t),
430                                            fcswils_init_count * sizeof(fcswils_conv_key_t),
431                                            G_ALLOC_AND_FREE);
432         fcswils_req_vals = g_mem_chunk_new("fcswils_req_vals",
433                                            sizeof(fcswils_conv_data_t),
434                                            fcswils_init_count * sizeof(fcswils_conv_data_t),
435                                            G_ALLOC_AND_FREE);
436 }
437
438 static gchar *
439 zonenm_to_str (tvbuff_t *tvb, gint offset)
440 {
441     int len = tvb_get_guint8 (tvb, offset);
442     return ((gchar *)tvb_get_ptr (tvb, offset+4, len));
443 }
444
445 /* Offset points to the start of the zone object */
446 static gint
447 get_zoneobj_len (tvbuff_t *tvb, gint offset)
448 {
449     gint numrec, numrec1;
450     guint8 objtype;
451     gint i, j, len;
452
453     /* zone object structure is:
454      * type (1 byte), protocol (1 byte), rsvd (2 bytes), obj name (x bytes),
455      * num of zone mbrs (4 bytes ), list of zone members (each member if of
456      * variable length).
457      *
458      * zone member structure is:
459      * type (1 byte), rsvd (1 byte), flags (1 byte), id_len (1 byte),
460      * id (id_len bytes)
461      */
462     objtype = tvb_get_guint8 (tvb, offset);
463     len = 4 + ZONENAME_LEN (tvb, offset+4); /* length upto num_of_mbrs field */
464     numrec = tvb_get_ntohl (tvb, offset+len); /* gets us num of zone mbrs */
465
466     len += 4;                   /* + num_mbrs */
467     for (i = 0; i < numrec; i++) {
468         if (objtype == FC_SWILS_ZONEOBJ_ZONESET) {
469             len += 4 + ZONENAME_LEN (tvb, offset+4+len); /* length upto num_of_mbrs field */
470             numrec1 = tvb_get_ntohl (tvb, offset+len);
471
472             len += 4;
473             for (j = 0; j < numrec1; j++) {
474                 len += 4 + tvb_get_guint8 (tvb, offset+3+len);
475             }
476         }
477         else if (objtype == FC_SWILS_ZONEOBJ_ZONE) {
478             len += 4 + tvb_get_guint8 (tvb, offset+3+len);
479         }
480     }
481
482     return len;
483 }
484
485 static void
486 dissect_swils_elp (tvbuff_t *tvb, proto_tree *elp_tree, guint8 isreq _U_)
487 {
488     
489     /* Set up structures needed to add the protocol subtree and manage it */
490     int offset = 0,
491         stroff = 0;
492     gchar flags[40];
493     fcswils_elp elp;
494
495     /* Response i.e. SW_ACC for an ELP has the same format as the request */
496     /* We skip the initial 4 bytes as we don't care about the opcode */
497     tvb_memcpy (tvb, (guint8 *)&elp, 4, FC_SWILS_ELP_SIZE);
498     
499     elp.r_a_tov = ntohl (elp.r_a_tov);
500     elp.e_d_tov = ntohl (elp.e_d_tov);
501     elp.isl_flwctrl_mode = ntohs (elp.isl_flwctrl_mode);
502     elp.flw_ctrl_parmlen = ntohs (elp.flw_ctrl_parmlen);
503     
504     if (elp_tree) {
505         offset += 4;
506         proto_tree_add_item (elp_tree, hf_swils_elp_rev, tvb, offset++, 1, 0);
507         proto_tree_add_item (elp_tree, hf_swils_elp_flags, tvb, offset, 2, 0);
508         offset += 3;
509         proto_tree_add_uint_format (elp_tree, hf_swils_elp_r_a_tov, tvb, offset, 4,
510                                     elp.r_a_tov, "R_A_TOV: %d msecs", elp.r_a_tov);
511         offset += 4;
512         proto_tree_add_uint_format (elp_tree, hf_swils_elp_e_d_tov, tvb, offset, 4,
513                                     elp.e_d_tov, "E_D_TOV: %d msecs", elp.e_d_tov);
514         offset += 4;
515         proto_tree_add_string (elp_tree, hf_swils_elp_req_epn, tvb, offset, 8,
516                                fcwwn_to_str (elp.req_epname));
517         offset += 8;
518         proto_tree_add_string (elp_tree, hf_swils_elp_req_esn, tvb, offset, 8,
519                                fcwwn_to_str (elp.req_sname));
520         offset += 8;
521
522         flags[0] = '\0';
523         if (elp.clsf_svcparm[0] & 0x80) {
524             strcpy (flags, "Class F Valid");
525
526             if (elp.clsf_svcparm[4] & 0x20) {
527                 strcpy (&flags[13], " | X_ID Interlock");
528             }
529             else {
530                 strcpy (&flags[13], " | No X_ID Interlk");
531             }
532         }
533         else {
534             strcpy (flags, "Class F Invld");
535         }
536         proto_tree_add_bytes_format (elp_tree, hf_swils_elp_clsf_svcp, tvb, offset, 6, 
537                                      &elp.clsf_svcparm[0], "Class F Svc Parameters: (%s)", flags);
538         offset += 6;
539
540         proto_tree_add_item (elp_tree, hf_swils_elp_clsf_rcvsz, tvb, offset, 2, 0);
541         offset += 2;
542         proto_tree_add_item (elp_tree, hf_swils_elp_clsf_conseq, tvb, offset, 2, 0);
543         offset += 2;
544         proto_tree_add_item (elp_tree, hf_swils_elp_clsf_e2e, tvb, offset, 2, 0);
545         offset += 2;
546         proto_tree_add_item (elp_tree, hf_swils_elp_clsf_openseq, tvb, offset, 2, 0);
547         offset += 4;
548
549         flags[0] = '\0';
550         stroff = 0;
551         if (elp.cls1_svcparm[0] & 0x80) {
552             strcpy (&flags[stroff], "Class 1 Valid");
553             stroff += 13;
554             if (elp.cls1_svcparm[0] & 0x40) {
555                 strcpy (&flags[stroff], " | IMX");
556                 stroff += 6;
557             }
558             if (elp.cls1_svcparm[0] & 0x20) {
559                 strcpy (&flags[stroff], " | XPS");
560                 stroff += 6;
561             }
562             if (elp.cls1_svcparm[0] & 0x10) {
563                 strcpy (&flags[stroff], " | LKS");
564             }
565         }
566         else {
567             strcpy (&flags[0], "Class 1 Invalid");
568         }
569         
570         proto_tree_add_bytes_format (elp_tree, hf_swils_elp_cls1_svcp, tvb, offset, 2,
571                                      tvb_get_ptr (tvb, offset, 2),
572                                      "Class 1 Svc Parameters: (%s)", flags);
573         offset += 2;
574         if (elp.cls1_svcparm[0] & 0x80) {
575             proto_tree_add_item (elp_tree, hf_swils_elp_cls1_rcvsz, tvb, offset, 2, 0);
576         }
577         offset += 2;
578
579         flags[0] = '\0';
580         if (elp.cls2_svcparm[0] & 0x80) {
581             strcpy (flags, "Class 2 Valid");
582
583             if (elp.cls2_svcparm[0] & 0x08) {
584                 strcpy (&flags[13], " | Seq Delivery");
585             }
586             else {
587                 strcpy (&flags[13], " | No Seq Delivery");
588             }
589         }
590         else {
591             strcpy (flags, "Class 2 Invld");
592         }
593         
594         proto_tree_add_bytes_format (elp_tree, hf_swils_elp_cls2_svcp, tvb, offset, 2,
595                                      &elp.cls2_svcparm[0],
596                                      "Class 2 Svc Parameters: (%s)", flags);
597         offset += 2;
598         
599         if (elp.cls2_svcparm[0] & 0x80) {
600             proto_tree_add_item (elp_tree, hf_swils_elp_cls2_rcvsz, tvb, offset, 2, 0);
601         }
602         offset += 2;
603         
604         flags[0] = '\0';
605         if (elp.cls3_svcparm[0] & 0x80) {
606             strcpy (flags, "Class 3 Valid");
607
608             if (elp.cls3_svcparm[0] & 0x08) {
609                 strcpy (&flags[13], " | Seq Delivery");
610             }
611             else {
612                 strcpy (&flags[13], " | No Seq Delivery");
613             }
614         }
615         else {
616             strcpy (flags, "Class 3 Invld");
617         }
618         proto_tree_add_bytes_format (elp_tree, hf_swils_elp_cls3_svcp, tvb, offset, 2,
619                                      &elp.cls3_svcparm[0],
620                                      "Class 3 Svc Parameters: (%s)", flags);
621         offset += 2;
622
623         if (elp.cls3_svcparm[0] & 0x80) {
624             proto_tree_add_item (elp_tree, hf_swils_elp_cls3_rcvsz, tvb, offset, 2, 0);
625         }
626         offset += 22;
627
628         proto_tree_add_string (elp_tree, hf_swils_elp_isl_fc_mode, tvb, offset, 2,
629                                val_to_str (elp.isl_flwctrl_mode, fcswils_elp_fc_val, "Vendor Unique"));
630         offset += 2;
631         proto_tree_add_item (elp_tree, hf_swils_elp_fcplen, tvb, offset, 2, 0);
632         offset += 2;
633         proto_tree_add_item (elp_tree, hf_swils_elp_b2bcredit, tvb, offset, 4, 0);
634         offset += 4;
635         proto_tree_add_item (elp_tree, hf_swils_elp_compat1, tvb, offset, 4, 0);
636         offset += 4;
637         proto_tree_add_item (elp_tree, hf_swils_elp_compat2, tvb, offset, 4, 0);
638         offset += 4;
639         proto_tree_add_item (elp_tree, hf_swils_elp_compat3, tvb, offset, 4, 0);
640         offset += 4;
641         proto_tree_add_item (elp_tree, hf_swils_elp_compat4, tvb, offset, 4, 0);
642     }
643
644 }
645
646 static void
647 dissect_swils_efp (tvbuff_t *tvb, proto_tree *efp_tree, guint8 isreq _U_)
648 {
649
650 /* Set up structures needed to add the protocol subtree and manage it */
651     proto_item *subti;
652     proto_tree *lrec_tree;
653     int num_listrec = 0,
654         offset = 0;
655     fcswils_efp efp;
656     fcswils_efp_listrec *lrec;
657     
658     tvb_memcpy (tvb, (guint8 *)&efp, offset, FC_SWILS_EFP_SIZE);
659     efp.payload_len = ntohs (efp.payload_len);
660     efp.listrec = (fcswils_efp_listrec *)tvb_get_ptr (tvb, FC_SWILS_EFP_SIZE,
661                                                       efp.payload_len - FC_SWILS_EFP_SIZE);
662     
663     if (efp_tree) {
664         offset += 2;
665         proto_tree_add_item (efp_tree, hf_swils_efp_payload_len, tvb, offset, 2, 0);
666         offset += 5;
667         proto_tree_add_item (efp_tree, hf_swils_efp_pswitch_pri, tvb,
668                              offset++, 1, 0);
669         proto_tree_add_string (efp_tree, hf_swils_efp_pswitch_name, tvb, offset,
670                                8, fcwwn_to_str (efp.pswitch_name));
671         offset += 8;
672
673         /* Add List Records now */
674         if (efp.reclen) {
675             num_listrec = (efp.payload_len - FC_SWILS_EFP_SIZE)/efp.reclen;
676         }
677         else {
678             num_listrec = 0;
679         }
680         
681         while (num_listrec--) {
682             lrec =  (fcswils_efp_listrec *)tvb_get_ptr (tvb, offset, efp.reclen);
683             if (lrec != NULL) {
684                 if (lrec->didrec.rec_type == FC_SWILS_LRECTYPE_DOMAIN) {
685                     subti = proto_tree_add_text (efp_tree, tvb, offset,
686                                                  (efp.payload_len - FC_SWILS_EFP_SIZE),
687                                                  "Domain ID Record");
688                     lrec_tree = proto_item_add_subtree (subti, ett_fcswils_efplist);
689                     proto_tree_add_item (lrec_tree, hf_swils_efp_dom_id, tvb, offset+1, 1, 0); 
690                     proto_tree_add_string (lrec_tree, hf_swils_efp_switch_name, tvb, offset+8, 8,
691                                            fcwwn_to_str (lrec->didrec.sname));
692                 }
693                 else if (lrec->didrec.rec_type == FC_SWILS_LRECTYPE_MCAST) {
694                     subti = proto_tree_add_text (efp_tree, tvb, offset,
695                                                  (efp.payload_len - FC_SWILS_EFP_SIZE),
696                                                  "Multicast ID Record");
697                     lrec_tree = proto_item_add_subtree (subti, ett_fcswils_efplist);
698                     proto_tree_add_item (lrec_tree, hf_swils_efp_mcast_grpno, tvb, offset+1, 1, 0);  
699                 }
700                 offset += efp.reclen;
701             }
702         }
703     }
704 }
705
706 static void
707 dissect_swils_dia (tvbuff_t *tvb, proto_tree *dia_tree, guint8 isreq _U_)
708 {
709     /* Set up structures needed to add the protocol subtree and manage it */
710     int offset = 0;
711
712     if (dia_tree) {
713         proto_tree_add_string (dia_tree, hf_swils_dia_switch_name, tvb, offset+4,
714                                8, fcwwn_to_str (tvb_get_ptr (tvb, offset+4, 8)));
715     }
716 }
717
718 static void
719 dissect_swils_rdi (tvbuff_t *tvb, proto_tree *rdi_tree, guint8 isreq)
720 {
721     /* Set up structures needed to add the protocol subtree and manage it */
722     int offset = 0;
723     int i, plen, numrec;
724     
725     if (rdi_tree) {
726         plen = tvb_get_ntohs (tvb, offset+2);
727         
728         proto_tree_add_item (rdi_tree, hf_swils_rdi_payload_len, tvb, offset+2, 2, 0);
729         proto_tree_add_string (rdi_tree, hf_swils_rdi_req_sname, tvb, offset+4,
730                                8, fcwwn_to_str (tvb_get_ptr (tvb, offset+4, 8)));
731
732         /* 12 is the length of the initial header and 4 is the size of each
733          * domain request record.
734          */
735         numrec = (plen - 12)/4;
736         offset = 12;
737         for (i = 0; i < numrec; i++) {
738             if (isreq) {
739                 proto_tree_add_text (rdi_tree, tvb, offset+3, 1,
740                                      "Requested Domain ID: %d",
741                                      tvb_get_guint8 (tvb, offset+3));
742             }
743             else {
744                 proto_tree_add_text (rdi_tree, tvb, offset+3, 1,
745                                      "Granted Domain ID: %d",
746                                      tvb_get_guint8 (tvb, offset+3));
747             }
748             offset += 4;
749         }
750     }
751 }
752
753 static void
754 dissect_swils_fspf_hdr (tvbuff_t *tvb, proto_tree *tree, int offset)
755 {
756     proto_item *subti;
757     proto_tree *fspfh_tree;
758     
759     if (tree) {
760         /* 20 is the size of FSPF header */
761         subti = proto_tree_add_text (tree, tvb, offset, 20, "FSPF Header");
762         fspfh_tree = proto_item_add_subtree (subti, ett_fcswils_fspfhdr);
763
764         proto_tree_add_item (fspfh_tree, hf_swils_fspfh_rev, tvb, offset+4,
765                              1, 0);
766         proto_tree_add_item (fspfh_tree, hf_swils_fspfh_ar_num, tvb,
767                              offset+5, 1, 0);
768         proto_tree_add_item (fspfh_tree, hf_swils_fspfh_auth_type, tvb,
769                              offset+6, 1, 0);
770         proto_tree_add_item (fspfh_tree, hf_swils_fspfh_dom_id, tvb, offset+11,
771                              1, 0);
772         proto_tree_add_item (fspfh_tree, hf_swils_fspfh_auth, tvb, offset+12,
773                              8, 0);
774     }
775 }
776
777 static void
778 dissect_swils_fspf_lsrechdr (tvbuff_t *tvb, proto_tree *tree, int offset)
779 {
780     proto_tree_add_item (tree, hf_swils_lsrh_lsr_type, tvb, offset, 1, 0);
781     proto_tree_add_text (tree, tvb, offset+2, 2, "LSR Age: %d secs",
782                          tvb_get_ntohs (tvb, offset+2));
783     proto_tree_add_text (tree, tvb, offset+4, 4, "Options : 0x%x",
784                          tvb_get_ntohl (tvb, offset+4));
785     proto_tree_add_item (tree, hf_swils_lsrh_lsid, tvb, offset+11, 1, 0);
786     proto_tree_add_item (tree, hf_swils_lsrh_adv_domid, tvb, offset+15, 1, 0);
787     proto_tree_add_item (tree, hf_swils_lsrh_ls_incid, tvb, offset+16, 4, 0);
788     proto_tree_add_text (tree, tvb, offset+20, 2, "Checksum: 0x%x",
789                          tvb_get_ntohs (tvb, offset+20));
790     proto_tree_add_text (tree, tvb, offset+22, 2, "LSR Length: %d",
791                          tvb_get_ntohs (tvb, offset+22));
792 }
793
794 static void
795 dissect_swils_fspf_ldrec (tvbuff_t *tvb, proto_tree *tree, int offset)
796 {
797     proto_tree_add_string (tree, hf_swils_ldrec_linkid, tvb, offset, 4,
798                            fc_to_str (tvb_get_ptr (tvb, offset+1, 3)));
799     proto_tree_add_item (tree, hf_swils_ldrec_out_pidx, tvb, offset+5, 3, 0);
800     proto_tree_add_item (tree, hf_swils_ldrec_nbr_pidx, tvb, offset+9, 3, 0);
801     proto_tree_add_item (tree, hf_swils_ldrec_link_type, tvb, offset+12, 1, 0);
802     proto_tree_add_item (tree, hf_swils_ldrec_link_cost, tvb, offset+14, 2, 0);
803 }
804
805 static void
806 dissect_swils_fspf_lsrec (tvbuff_t *tvb, proto_tree *tree, int offset,
807                           int num_lsrec)
808 {
809     int i, j, num_ldrec;
810     proto_item *subti1, *subti;
811     proto_tree *lsrec_tree, *ldrec_tree, *lsrechdr_tree;
812
813     if (tree) {
814         for (j = 0; j < num_lsrec; j++) {
815             num_ldrec = tvb_get_ntohs (tvb, offset+26); 
816             subti = proto_tree_add_text (tree, tvb, offset, (28+num_ldrec*16),
817                                          "Link State Record %d (Domain %d)", j,
818                                          tvb_get_guint8 (tvb, offset+15));
819             lsrec_tree = proto_item_add_subtree (subti, ett_fcswils_lsrec);
820         
821             subti = proto_tree_add_text (lsrec_tree, tvb, offset, 24,
822                                          "Link State Record Header");
823             lsrechdr_tree = proto_item_add_subtree (subti,
824                                                     ett_fcswils_lsrechdr); 
825         
826             dissect_swils_fspf_lsrechdr (tvb, lsrechdr_tree, offset);
827             proto_tree_add_text (tree, tvb, offset+26, 2, "Number of Links: %d",
828                                  num_ldrec);
829             offset += 28;
830         
831             for (i = 0; i < num_ldrec; i++) {
832                 subti1 = proto_tree_add_text (lsrec_tree, tvb, offset, 16,
833                                               "Link Descriptor %d "
834                                               "(Neighbor domain %d)", i,
835                                               tvb_get_guint8 (tvb, offset+3));
836                 ldrec_tree = proto_item_add_subtree (subti1, ett_fcswils_ldrec);
837                 dissect_swils_fspf_ldrec (tvb, ldrec_tree, offset);
838                 offset += 16;
839             }
840         }
841     }
842 }
843
844 static void
845 dissect_swils_hello (tvbuff_t *tvb, proto_tree *hlo_tree, guint8 isreq _U_)
846 {
847     /* Set up structures needed to add the protocol subtree and manage it */
848     int offset = 0;
849
850     if (hlo_tree) {
851         dissect_swils_fspf_hdr (tvb, hlo_tree, offset);
852
853         proto_tree_add_item (hlo_tree, hf_swils_hlo_options, tvb, offset+20, 4, 0);
854         proto_tree_add_item (hlo_tree, hf_swils_hlo_hloint, tvb, offset+24, 4, 0);
855         proto_tree_add_item (hlo_tree, hf_swils_hlo_deadint, tvb, offset+28, 4, 0);
856         proto_tree_add_item (hlo_tree, hf_swils_hlo_rcv_domid, tvb, offset+35, 1, 0);
857         proto_tree_add_item (hlo_tree, hf_swils_hlo_orig_pidx, tvb, offset+37, 3, 0);
858     }
859 }
860
861 static void
862 dissect_swils_lsupdate (tvbuff_t *tvb, proto_tree *lsu_tree, guint8 isreq _U_)
863 {
864     /* Set up structures needed to add the protocol subtree and manage it */
865     int offset = 0;
866     int num_lsrec;
867
868     if (lsu_tree) {
869         dissect_swils_fspf_hdr (tvb, lsu_tree, offset);
870
871         proto_tree_add_text (lsu_tree, tvb, offset+23, 1, "Flags : %s",
872                              val_to_str (tvb_get_guint8 (tvb, offset+23),
873                                          fc_swils_fspf_lsrflags_val, "0x%x"));
874         num_lsrec = tvb_get_ntohl (tvb, offset+24);
875
876         proto_tree_add_text (lsu_tree, tvb, offset+24, 4, "Num of LSRs: %d",
877                              num_lsrec);
878
879         offset = 28;
880         dissect_swils_fspf_lsrec (tvb, lsu_tree, offset, num_lsrec);
881     }
882 }
883
884 static void
885 dissect_swils_lsack (tvbuff_t *tvb, proto_tree *lsa_tree, guint8 isreq _U_)
886 {
887     /* Set up structures needed to add the protocol subtree and manage it */
888     int offset = 0;
889     int num_lsrechdr, i;
890     proto_item *subti;
891     proto_tree *lsrechdr_tree;
892
893     if (lsa_tree) {
894         dissect_swils_fspf_hdr (tvb, lsa_tree, offset);
895
896         proto_tree_add_text (lsa_tree, tvb, offset+23, 1, "Flags : %s",
897                              val_to_str (tvb_get_guint8 (tvb, offset+23),
898                                          fc_swils_fspf_lsrflags_val, "0x%x"));
899         num_lsrechdr = tvb_get_ntohl (tvb, offset+24);
900
901         proto_tree_add_text (lsa_tree, tvb, offset+24, 4, "Num of LSR Headers: %d",
902                              num_lsrechdr);
903
904         offset = 28;
905
906         for (i = 0; i < num_lsrechdr; i++) {
907             subti = proto_tree_add_text (lsa_tree, tvb, offset, 24,
908                                          "Link State Record Header (Domain %d)",
909                                          tvb_get_guint8 (tvb, offset+15));
910             lsrechdr_tree = proto_item_add_subtree (subti,
911                                                     ett_fcswils_lsrechdr); 
912             dissect_swils_fspf_lsrechdr (tvb, lsrechdr_tree, offset);
913             offset += 24;
914         }
915     }
916 }
917
918 static void
919 dissect_swils_rscn (tvbuff_t *tvb, proto_tree *rscn_tree, guint8 isreq)
920 {
921     /* Set up structures needed to add the protocol subtree and manage it */
922     int offset = 0;
923     proto_tree *dev_tree;
924     int addrfmt, evtype;
925     int numrec, i;
926     proto_item *subti;
927     
928     if (rscn_tree) {
929         if (!isreq)
930             return;
931         
932         evtype = tvb_get_guint8 (tvb, offset+4);
933         addrfmt = evtype & 0x0F;
934         evtype = evtype >> 4;
935
936         proto_tree_add_item (rscn_tree, hf_swils_rscn_evtype, tvb, offset+4,
937                              1, 0);
938         proto_tree_add_item (rscn_tree, hf_swils_rscn_addrfmt, tvb, offset+4,
939                              1, 0);
940         proto_tree_add_string (rscn_tree, hf_swils_rscn_affectedport, tvb,
941                                offset+5, 3, fc_to_str (tvb_get_ptr (tvb,
942                                                                     offset+5, 3)));
943         proto_tree_add_item (rscn_tree, hf_swils_rscn_detectfn, tvb,
944                              offset+8, 4, 0);
945         numrec = tvb_get_ntohl (tvb, offset+12);
946         
947         if (!tvb_bytes_exist (tvb, offset+16, FC_SWILS_RSCN_DEVENTRY_SIZE*numrec)) {
948             /* Some older devices do not include device entry information. */
949             return;
950         }
951         
952         proto_tree_add_text (rscn_tree, tvb, offset+12, 4, "Num Entries: %d",
953                              numrec);
954
955         offset = 16;
956         for (i = 0; i < numrec; i++) {
957             subti = proto_tree_add_text (rscn_tree, tvb, offset, 20,
958                                          "Device Entry %d", i);
959             dev_tree = proto_item_add_subtree (rscn_tree, ett_fcswils_rscn_dev);
960
961             proto_tree_add_item (dev_tree, hf_swils_rscn_portstate, tvb, offset, 1, 0);
962             proto_tree_add_string (dev_tree, hf_swils_rscn_portid, tvb, offset+1, 3,
963                                    fc_to_str (tvb_get_ptr (tvb, offset+1, 3)));
964             proto_tree_add_string (dev_tree, hf_swils_rscn_pwwn, tvb, offset+4, 8,
965                                    fcwwn_to_str (tvb_get_ptr (tvb, offset+4, 8)));
966             proto_tree_add_string (dev_tree, hf_swils_rscn_nwwn, tvb, offset+12, 8,
967                                    fcwwn_to_str (tvb_get_ptr (tvb, offset+12, 8)));
968             offset += 20;
969         }
970     }
971 }
972
973 /*
974  * Merge Request contains zoning objects organized in the following format:
975  *
976  * Zone Set Object
977  *      |
978  *      +---------------- Zone Object
979  *      |                      |
980  *      +--                    +---------------- Zone Member
981  *      |                      |                     |
982  *      +--                    +----                 +-----
983  *
984  * So the decoding of the zone merge request is based on this structure
985  */
986
987 static void
988 dissect_swils_zone_mbr (tvbuff_t *tvb, proto_tree *zmbr_tree, int offset)
989 {
990     int mbrlen = 4 + tvb_get_guint8 (tvb, offset+3);
991
992     proto_tree_add_item (zmbr_tree, hf_swils_zone_mbrtype, tvb,
993                          offset, 1, 0);
994     proto_tree_add_text (zmbr_tree, tvb, offset+2, 1, "Flags: 0x%x",
995                          tvb_get_guint8 (tvb, offset+2));
996     proto_tree_add_text (zmbr_tree, tvb, offset+3, 1,
997                          "Identifier Length: %d",
998                          tvb_get_guint8 (tvb, offset+3));
999     switch (tvb_get_guint8 (tvb, offset)) {
1000     case FC_SWILS_ZONEMBR_WWN:
1001         proto_tree_add_string (zmbr_tree, hf_swils_zone_mbrid, tvb,
1002                                offset+4, 8,
1003                                fcwwn_to_str (tvb_get_ptr (tvb,
1004                                                           offset+4,
1005                                                           8)));
1006         break;
1007     case FC_SWILS_ZONEMBR_DP:
1008         proto_tree_add_string_format (zmbr_tree,
1009                                       hf_swils_zone_mbrid,
1010                                       tvb, offset+4, 4, " ",
1011                                       "0x%x",
1012                                       tvb_get_ntohl (tvb,
1013                                                      offset+4));
1014         break;
1015     case FC_SWILS_ZONEMBR_FCID:
1016         proto_tree_add_string (zmbr_tree, hf_swils_zone_mbrid, tvb,
1017                                offset+4, 4,
1018                                fc_to_str (tvb_get_ptr (tvb,
1019                                                        offset+5,
1020                                                        3)));
1021         break;
1022     case FC_SWILS_ZONEMBR_ALIAS:
1023         proto_tree_add_string (zmbr_tree, hf_swils_zone_mbrid, tvb,
1024                                offset+4,
1025                                tvb_get_guint8 (tvb, offset+3),
1026                                zonenm_to_str (tvb, offset+4));
1027         break;
1028     case FC_SWILS_ZONEMBR_WWN_LUN:
1029         proto_tree_add_string (zmbr_tree, hf_swils_zone_mbrid, tvb,
1030                                offset+4, 8,
1031                                fcwwn_to_str (tvb_get_ptr (tvb,
1032                                                           offset+4,
1033                                                           8)));
1034         proto_tree_add_item (zmbr_tree, hf_swils_zone_mbrid_lun, tvb,
1035                              offset+12, 8, 0);
1036         break;
1037     case FC_SWILS_ZONEMBR_DP_LUN:
1038         proto_tree_add_string_format (zmbr_tree,
1039                                       hf_swils_zone_mbrid,
1040                                       tvb, offset+4, 4, " ",
1041                                       "0x%x",
1042                                       tvb_get_ntohl (tvb,
1043                                                      offset+4));
1044         proto_tree_add_item (zmbr_tree, hf_swils_zone_mbrid_lun, tvb,
1045                              offset+8, 8, 0);
1046         break;
1047     case FC_SWILS_ZONEMBR_FCID_LUN:
1048         proto_tree_add_string (zmbr_tree, hf_swils_zone_mbrid, tvb,
1049                                offset+4, 4,
1050                                fc_to_str (tvb_get_ptr (tvb,
1051                                                        offset+5,
1052                                                        3)));
1053         proto_tree_add_item (zmbr_tree, hf_swils_zone_mbrid_lun, tvb,
1054                              offset+8, 8, 0);
1055         break;
1056     default:
1057         proto_tree_add_string (zmbr_tree, hf_swils_zone_mbrid, tvb,
1058                                offset+4, mbrlen,
1059                                "Unknown member type format");
1060             
1061     }
1062 }
1063
1064 static void
1065 dissect_swils_zone_obj (tvbuff_t *tvb, proto_tree *zobj_tree, int offset)
1066 {
1067     proto_tree *zmbr_tree;
1068     int mbrlen, numrec, i, objtype;
1069     proto_item *subti;
1070
1071     objtype = tvb_get_guint8 (tvb, offset);
1072     
1073     proto_tree_add_item (zobj_tree, hf_swils_zone_objtype, tvb, offset,
1074                          1, 0);
1075     proto_tree_add_item (zobj_tree, hf_swils_zone_protocol, tvb,
1076                          offset+1, 1, 0);
1077     proto_tree_add_string (zobj_tree, hf_swils_zone_objname, tvb,
1078                            offset+4, ZONENAME_LEN (tvb, offset+4),
1079                            zonenm_to_str (tvb, offset+4));
1080
1081     numrec = tvb_get_ntohl (tvb, offset+4+ZONENAME_LEN (tvb, offset+4));
1082     proto_tree_add_text (zobj_tree, tvb,
1083                          offset+4+ZONENAME_LEN (tvb, offset+4), 4,
1084                          "Number of Zone Members: %d", numrec);
1085
1086     offset += 8 + ZONENAME_LEN (tvb, offset+4);
1087     for (i = 0; i < numrec; i++) {
1088         if (objtype == FC_SWILS_ZONEOBJ_ZONESET) {
1089             dissect_swils_zone_obj (tvb, zobj_tree, offset);
1090             offset += get_zoneobj_len (tvb, offset);
1091         }
1092         else {
1093             mbrlen = 4 + tvb_get_guint8 (tvb, offset+3);
1094             subti = proto_tree_add_text (zobj_tree, tvb, offset, mbrlen,
1095                                          "Zone Member %d", i);
1096             zmbr_tree = proto_item_add_subtree (zobj_tree,
1097                                                 ett_fcswils_zonembr);
1098             dissect_swils_zone_mbr (tvb, zmbr_tree, offset);
1099             offset += mbrlen;
1100         }
1101     }
1102 }
1103
1104 static void
1105 dissect_swils_mergereq (tvbuff_t *tvb, proto_tree *mr_tree, guint8 isreq)
1106 {
1107     /* Set up structures needed to add the protocol subtree and manage it */
1108     int offset = 0;
1109     proto_tree *zobjlist_tree, *zobj_tree;
1110     int numrec, i, zonesetlen, objlistlen, objlen;
1111     proto_item *subti;
1112
1113     if (mr_tree) {
1114         if (isreq) {
1115             /* zonesetlen is the size of the zoneset including the zone name */ 
1116             zonesetlen = tvb_get_ntohs (tvb, offset+2);
1117             proto_tree_add_text (mr_tree, tvb, offset+2, 2,
1118                                  "Active ZoneSet Length: %d", zonesetlen);
1119
1120             if (zonesetlen) {
1121                 proto_tree_add_string (mr_tree, hf_swils_zone_activezonenm, tvb,
1122                                        offset+4, ZONENAME_LEN (tvb, offset+4),
1123                                        zonenm_to_str (tvb, offset+4));
1124                 
1125                 /* objlistlen gives the size of the active zoneset object list */ 
1126                 objlistlen = zonesetlen - ZONENAME_LEN (tvb, offset+4);
1127                 /* Offset = start of the active zoneset zoning object list */
1128                 offset = offset + (4 + ZONENAME_LEN (tvb, offset+4));
1129                 numrec = tvb_get_ntohl (tvb, offset);
1130                 
1131                 subti = proto_tree_add_text (mr_tree, tvb, offset, objlistlen,
1132                                              "Active Zone Set");
1133                 zobjlist_tree = proto_item_add_subtree (subti,
1134                                                         ett_fcswils_zoneobjlist);
1135                 
1136                 proto_tree_add_text (zobjlist_tree, tvb, offset, 4,
1137                                      "Number of zoning objects: %d", numrec);
1138
1139                 offset += 4;
1140                 for (i = 0; i < numrec; i++) {
1141                     objlen = get_zoneobj_len (tvb, offset);
1142                     subti = proto_tree_add_text (zobjlist_tree, tvb, offset+4,
1143                                                  objlen, "Zone Object %d", i);
1144                     zobj_tree = proto_item_add_subtree (subti, ett_fcswils_zoneobj);
1145                     dissect_swils_zone_obj (tvb, zobj_tree, offset);
1146                     offset += objlen;
1147                 }
1148             }
1149             else {
1150                 offset += 4;
1151             }
1152             
1153             zonesetlen = tvb_get_ntohl (tvb, offset);
1154             proto_tree_add_text (mr_tree, tvb, offset, 4,
1155                                  "Full Zone Set Length: %d", zonesetlen);
1156
1157             if (zonesetlen) {
1158                 objlistlen = zonesetlen;
1159                 /* Offset = start of the active zoneset zoning object list */
1160                 offset += 4;
1161                 numrec = tvb_get_ntohl (tvb, offset);
1162                 
1163                 subti = proto_tree_add_text (mr_tree, tvb, offset, objlistlen,
1164                                              "Full Zone Set");
1165                 
1166                 zobjlist_tree = proto_item_add_subtree (subti,
1167                                                         ett_fcswils_zoneobjlist);
1168                 proto_tree_add_text (zobjlist_tree, tvb, offset, 4,
1169                                      "Number of zoning objects: %d", numrec);
1170                 offset += 4;
1171                 for (i = 0; i < numrec; i++) {
1172                     objlen = get_zoneobj_len (tvb, offset);
1173                     subti = proto_tree_add_text (zobjlist_tree, tvb, offset,
1174                                                  objlen, "Zone Object %d", i);
1175                     zobj_tree = proto_item_add_subtree (subti, ett_fcswils_zoneobj);
1176                     dissect_swils_zone_obj (tvb, zobj_tree, offset);
1177                     offset += objlen;
1178                 }
1179             }
1180         }
1181         else {
1182             proto_tree_add_item (mr_tree, hf_swils_zone_status, tvb,
1183                                  offset+5, 1, 0);
1184             proto_tree_add_item (mr_tree, hf_swils_zone_reason, tvb,
1185                                  offset+6, 1, 0);
1186             proto_tree_add_text (mr_tree, tvb, offset+7, 1,
1187                                  "Vendor Unique: 0x%x",
1188                                  tvb_get_guint8 (tvb, offset+7));
1189         }
1190     }
1191 }
1192
1193 static void
1194 dissect_swils_aca (tvbuff_t *tvb, proto_tree *aca_tree, guint8 isreq)
1195 {
1196     /* Set up structures needed to add the protocol subtree and manage it */
1197     int offset = 0;
1198     int numrec, plen, i;
1199
1200     if (aca_tree) {
1201         if (isreq) {
1202             plen = tvb_get_ntohs (tvb, offset+2);
1203             proto_tree_add_text (aca_tree, tvb, offset+2, 2,
1204                                  "Domain ID List Length: %d", plen);
1205             numrec = plen/4;
1206             offset = 4;
1207         
1208             for (i = 0; i < numrec; i++) {
1209                 proto_tree_add_uint_format (aca_tree, hf_swils_aca_domainid,
1210                                             tvb, offset+3, 1, 
1211                                             tvb_get_guint8 (tvb, offset+3),
1212                                             "Domain ID %d: %d", i,
1213                                             tvb_get_guint8 (tvb, offset+3));
1214                 offset += 4;
1215             }
1216         }
1217         else {
1218             proto_tree_add_item (aca_tree, hf_swils_zone_status, tvb,
1219                                  offset+5, 1, 0);
1220             proto_tree_add_item (aca_tree, hf_swils_zone_reason, tvb,
1221                                  offset+6, 1, 0);
1222             proto_tree_add_text (aca_tree, tvb, offset+7, 1,
1223                                  "Vendor Unique: 0x%x",
1224                                  tvb_get_guint8 (tvb, offset+7));
1225         }
1226     }
1227 }
1228
1229 static void
1230 dissect_swils_rca (tvbuff_t *tvb, proto_tree *rca_tree, guint8 isreq)
1231 {
1232     /* Set up structures needed to add the protocol subtree and manage it */
1233     int offset = 0;
1234
1235     if (rca_tree) {
1236         if (!isreq) {
1237             proto_tree_add_item (rca_tree, hf_swils_zone_status, tvb,
1238                                  offset+5, 1, 0);
1239             proto_tree_add_item (rca_tree, hf_swils_zone_reason, tvb,
1240                                  offset+6, 1, 0);
1241             proto_tree_add_text (rca_tree, tvb, offset+7, 1,
1242                                  "Vendor Unique: 0x%x",
1243                                  tvb_get_guint8 (tvb, offset+7));
1244         }
1245     }
1246 }
1247
1248 static void
1249 dissect_swils_sfc (tvbuff_t *tvb, proto_tree *sfc_tree, guint8 isreq)
1250 {
1251     /* Set up structures needed to add the protocol subtree and manage it */
1252     int offset = 0;
1253     proto_tree *zobjlist_tree, *zobj_tree;
1254     int numrec, i, zonesetlen, objlistlen, objlen;
1255     proto_item *subti;
1256
1257     if (sfc_tree) {
1258         if (isreq) {
1259             proto_tree_add_item (sfc_tree, hf_swils_sfc_opcode, tvb, offset+1, 1, 0);
1260
1261             zonesetlen = tvb_get_ntohs (tvb, offset+2);
1262             proto_tree_add_text (sfc_tree, tvb, offset+2, 2,
1263                                  "ZoneSet Length: %d", zonesetlen);
1264
1265             if (zonesetlen) {
1266                 proto_tree_add_string (sfc_tree, hf_swils_sfc_zonenm, tvb,
1267                                        offset+4, ZONENAME_LEN (tvb, offset+4),
1268                                        zonenm_to_str (tvb, offset+4));
1269                 
1270                 /* objlistlen gives the size of the active zoneset object list */ 
1271                 objlistlen = zonesetlen - ZONENAME_LEN (tvb, offset+4);
1272                 /* Offset = start of the active zoneset zoning object list */
1273                 offset = offset + (4 + ZONENAME_LEN (tvb, offset+4));
1274                 numrec = tvb_get_ntohl (tvb, offset);
1275                 
1276                 subti = proto_tree_add_text (sfc_tree, tvb, offset, objlistlen,
1277                                              "Zone Set");
1278                 zobjlist_tree = proto_item_add_subtree (subti,
1279                                                         ett_fcswils_zoneobjlist);
1280                 
1281                 proto_tree_add_text (zobjlist_tree, tvb, offset, 4,
1282                                      "Number of zoning objects: %d", numrec);
1283
1284                 offset += 4;
1285                 for (i = 0; i < numrec; i++) {
1286                     objlen = get_zoneobj_len (tvb, offset);
1287                     subti = proto_tree_add_text (zobjlist_tree, tvb, offset,
1288                                                  objlen, "Zone Object %d", i);
1289                     zobj_tree = proto_item_add_subtree (subti, ett_fcswils_zoneobj);
1290                     dissect_swils_zone_obj (tvb, zobj_tree, offset);
1291                     offset += objlen;
1292                 }
1293             }
1294             else {
1295                 offset += 4;
1296             }
1297
1298             zonesetlen = tvb_get_ntohl (tvb, offset);
1299             proto_tree_add_text (sfc_tree, tvb, offset, 4,
1300                                  "Full Zone Set Length: %d", zonesetlen);
1301
1302             if (zonesetlen) {
1303                 objlistlen = zonesetlen;
1304                 /* Offset = start of the active zoneset zoning object list */
1305                 offset += 4;
1306                 numrec = tvb_get_ntohl (tvb, offset);
1307                 
1308                 subti = proto_tree_add_text (sfc_tree, tvb, offset, objlistlen,
1309                                              "Full Zone Set");
1310                 
1311                 zobjlist_tree = proto_item_add_subtree (subti,
1312                                                         ett_fcswils_zoneobjlist);
1313                 proto_tree_add_text (zobjlist_tree, tvb, offset, 4,
1314                                      "Number of zoning objects: %d", numrec);
1315                 offset += 4;
1316                 for (i = 0; i < numrec; i++) {
1317                     objlen = get_zoneobj_len (tvb, offset);
1318                     subti = proto_tree_add_text (zobjlist_tree, tvb, offset,
1319                                                  objlen, "Zone Object %d", i);
1320                     zobj_tree = proto_item_add_subtree (subti, ett_fcswils_zoneobj);
1321                     dissect_swils_zone_obj (tvb, zobj_tree, offset);
1322                     offset += objlen;
1323                 }
1324             }
1325         }
1326         else {
1327             proto_tree_add_item (sfc_tree, hf_swils_zone_status, tvb,
1328                                  offset+5, 1, 0);
1329             proto_tree_add_item (sfc_tree, hf_swils_zone_reason, tvb,
1330                                  offset+6, 1, 0);
1331             proto_tree_add_text (sfc_tree, tvb, offset+7, 1,
1332                                  "Vendor Unique: 0x%x",
1333                                  tvb_get_guint8 (tvb, offset+7));
1334         }
1335     }
1336 }
1337
1338 static void
1339 dissect_swils_ufc (tvbuff_t *tvb, proto_tree *ufc_tree, guint8 isreq)
1340 {
1341     /* Set up structures needed to add the protocol subtree and manage it */
1342     int offset = 0;
1343
1344     if (ufc_tree) {
1345         if (!isreq) {
1346             proto_tree_add_item (ufc_tree, hf_swils_zone_status, tvb,
1347                                  offset+5, 1, 0);
1348             proto_tree_add_item (ufc_tree, hf_swils_zone_reason, tvb,
1349                                  offset+6, 1, 0);
1350             proto_tree_add_text (ufc_tree, tvb, offset+7, 1,
1351                                  "Vendor Unique: 0x%x",
1352                                  tvb_get_guint8 (tvb, offset+7));
1353         }
1354     }
1355 }
1356
1357 static void
1358 dissect_swils_esc (tvbuff_t *tvb, proto_tree *esc_tree, guint8 isreq)
1359 {
1360     /* Set up structures needed to add the protocol subtree and manage it */
1361     int offset = 0;
1362     int i, numrec, plen;
1363     proto_tree *pdesc_tree;
1364     proto_item *subti;
1365
1366     if (esc_tree) {
1367         if (isreq) {
1368             plen = tvb_get_ntohs (tvb, offset+2);
1369             proto_tree_add_text (esc_tree, tvb, offset+2, 2,
1370                                  "Payload Length: %d", plen);
1371             proto_tree_add_item (esc_tree, hf_swils_esc_swvendorid, tvb,
1372                                  offset+4, 8, 0);
1373             numrec = (plen - 12)/12;
1374             offset = 12;
1375
1376             for (i = 0; i < numrec; i++) {
1377                 subti = proto_tree_add_text (esc_tree, tvb, offset, 12,
1378                                              "Protocol Descriptor %d", i);
1379                 pdesc_tree = proto_item_add_subtree (subti,
1380                                                      ett_fcswils_esc_pdesc);
1381                 proto_tree_add_item (pdesc_tree, hf_swils_esc_pdesc_vendorid, tvb,
1382                                      offset, 8, 0);
1383                 proto_tree_add_item (pdesc_tree, hf_swils_esc_protocolid,
1384                                      tvb, offset+10, 2, 0);
1385                 offset += 12;
1386             }
1387         }
1388         else {
1389             proto_tree_add_item (esc_tree, hf_swils_esc_swvendorid, tvb,
1390                                  offset+4, 8, 0);
1391             subti = proto_tree_add_text (esc_tree, tvb, offset+12, 12,
1392                                          "Accepted Protocol Descriptor");
1393             pdesc_tree = proto_item_add_subtree (subti, ett_fcswils_esc_pdesc);
1394
1395             proto_tree_add_item (pdesc_tree, hf_swils_esc_pdesc_vendorid, tvb,
1396                                  offset+12, 8, 0);
1397             proto_tree_add_item (pdesc_tree, hf_swils_esc_protocolid,
1398                                  tvb, offset+22, 2, 0);
1399         }
1400     }
1401 }
1402
1403 static void
1404 dissect_swils_drlir (tvbuff_t *tvb _U_, proto_tree *drlir_tree _U_,
1405                      guint8 isreq _U_)
1406 {
1407     /* Set up structures needed to add the protocol subtree and manage it */
1408     return;
1409 }
1410
1411 static void
1412 dissect_swils_swrjt (tvbuff_t *tvb, proto_tree *swrjt_tree)
1413 {
1414     /* Set up structures needed to add the protocol subtree and manage it */
1415     int offset = 0;
1416
1417     if (swrjt_tree) {
1418         proto_tree_add_item (swrjt_tree, hf_swils_rjt, tvb, offset+5, 1, 0);
1419         proto_tree_add_item (swrjt_tree, hf_swils_rjtdet, tvb, offset+6, 1, 0);
1420         proto_tree_add_item (swrjt_tree, hf_swils_rjtvendor, tvb, offset+7,
1421                              1, 0);
1422     }
1423 }
1424
1425 /* Code to actually dissect the packets */
1426 static void
1427 dissect_fcswils (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1428 {
1429     proto_item *ti = NULL;
1430     guint8 opcode,
1431         failed_opcode = 0;
1432     int offset = 0;
1433     conversation_t *conversation;
1434     fcswils_conv_data_t *cdata;
1435     fcswils_conv_key_t ckey, *req_key;
1436     proto_tree *swils_tree = NULL;
1437     guint8 isreq = FC_SWILS_REQ;
1438     tvbuff_t *next_tvb;
1439
1440     /* Make entries in Protocol column and Info column on summary display */
1441     if (check_col(pinfo->cinfo, COL_PROTOCOL)) 
1442         col_set_str(pinfo->cinfo, COL_PROTOCOL, "SW_ILS");
1443
1444     /* decoding of this is done by each individual opcode handler */
1445     opcode = tvb_get_guint8 (tvb, 0);
1446     
1447     if (tree) {
1448         ti = proto_tree_add_protocol_format (tree, proto_fcswils, tvb, 0,
1449                                              tvb_length (tvb), "SW_ILS");
1450         swils_tree = proto_item_add_subtree (ti, ett_fcswils);
1451     }
1452
1453     /* Register conversation if this is not a response */
1454     if ((opcode != FC_SWILS_SWACC) && (opcode != FC_SWILS_SWRJT)) {
1455         conversation = find_conversation (&pinfo->src, &pinfo->dst,
1456                                           pinfo->ptype, pinfo->oxid,
1457                                           pinfo->rxid, NO_PORT2);
1458         if (!conversation) {
1459             conversation = conversation_new (&pinfo->src, &pinfo->dst,
1460                                              pinfo->ptype, pinfo->oxid,
1461                                              pinfo->rxid, NO_PORT2);
1462         }
1463     
1464         ckey.conv_idx = conversation->index;
1465         
1466         cdata = (fcswils_conv_data_t *)g_hash_table_lookup (fcswils_req_hash,
1467                                                             &ckey);
1468         if (cdata) {
1469             /* Since we never free the memory used by an exchange, this maybe a
1470              * case of another request using the same exchange as a previous
1471              * req. 
1472              */
1473             cdata->opcode = opcode;
1474         }
1475         else {
1476             req_key = g_mem_chunk_alloc (fcswils_req_keys);
1477             req_key->conv_idx = conversation->index;
1478             
1479             cdata = g_mem_chunk_alloc (fcswils_req_vals);
1480             cdata->opcode = opcode;
1481             
1482             g_hash_table_insert (fcswils_req_hash, req_key, cdata);
1483         }
1484     }
1485     else {
1486         /* Opcode is ACC or RJT */
1487         conversation = find_conversation (&pinfo->src, &pinfo->dst,
1488                                           pinfo->ptype, pinfo->oxid,
1489                                           pinfo->rxid, NO_PORT2);
1490         isreq = FC_SWILS_RPLY;
1491         if (!conversation) {
1492             if (tree && (opcode == FC_SWILS_SWACC)) {
1493                 /* No record of what this accept is for. Can't decode */
1494                 proto_tree_add_text (swils_tree, tvb, 0, tvb_length (tvb),
1495                                      "No record of Exchg. Unable to decode SW_ACC");
1496                 return;
1497             }
1498         }
1499         else {
1500             ckey.conv_idx = conversation->index;
1501
1502             cdata = (fcswils_conv_data_t *)g_hash_table_lookup (fcswils_req_hash, &ckey);
1503
1504             if (cdata != NULL) {
1505                 if (opcode == FC_SWILS_SWACC)
1506                     opcode = cdata->opcode;
1507                 else
1508                     failed_opcode = cdata->opcode;
1509             }
1510             
1511             if (tree) {
1512                 if ((cdata == NULL) && (opcode != FC_SWILS_SWRJT)) {
1513                     /* No record of what this accept is for. Can't decode */
1514                     proto_tree_add_text (swils_tree, tvb, 0, tvb_length (tvb),
1515                                          "No record of SW_ILS Req. Unable to decode SW_ACC");
1516                     return;
1517                 }
1518             }
1519         }
1520     }
1521
1522     if (check_col (pinfo->cinfo, COL_INFO)) {
1523         if (isreq == FC_SWILS_REQ) {
1524             col_add_str (pinfo->cinfo, COL_INFO,
1525                          val_to_str (opcode, fc_swils_opcode_key_val, "0x%x"));
1526         }
1527         else if (opcode == FC_SWILS_SWRJT) {
1528             col_add_fstr (pinfo->cinfo, COL_INFO, "SW_RJT (%s)",
1529                           val_to_str (failed_opcode, fc_swils_opcode_key_val, "0x%x"));
1530         }
1531         else {
1532             col_add_fstr (pinfo->cinfo, COL_INFO, "SW_ACC (%s)",
1533                           val_to_str (opcode, fc_swils_opcode_key_val, "0x%x"));
1534         }
1535     }
1536
1537     if (tree) {
1538         proto_tree_add_item (swils_tree, hf_swils_opcode, tvb, offset, 1, 0);
1539     }
1540
1541     switch (opcode) {
1542     case FC_SWILS_SWRJT:
1543         dissect_swils_swrjt (tvb, swils_tree);
1544         break;
1545     case FC_SWILS_ELP:
1546         dissect_swils_elp (tvb, swils_tree, isreq);
1547         break;
1548     case FC_SWILS_EFP:
1549         dissect_swils_efp (tvb, swils_tree, isreq);
1550         break;
1551     case FC_SWILS_DIA:
1552         dissect_swils_dia (tvb, swils_tree, isreq);
1553         break;
1554     case FC_SWILS_RDI:
1555         dissect_swils_rdi (tvb, swils_tree, isreq);
1556         break;
1557     case FC_SWILS_HLO:
1558         dissect_swils_hello (tvb, swils_tree, isreq);
1559         break;
1560     case FC_SWILS_LSU:
1561         dissect_swils_lsupdate (tvb, swils_tree, isreq);
1562         break;
1563     case FC_SWILS_LSA:
1564         dissect_swils_lsack (tvb, swils_tree, isreq);
1565         break;
1566     case FC_SWILS_BF:
1567     case FC_SWILS_RCF:
1568         /* Nothing to be displayed for these two commands */
1569         break;
1570     case FC_SWILS_RSCN:
1571         dissect_swils_rscn (tvb, swils_tree, isreq);
1572         break;
1573     case FC_SWILS_DRLIR:
1574         dissect_swils_drlir (tvb, swils_tree, isreq);
1575         break;
1576     case FC_SWILS_MR:
1577         dissect_swils_mergereq (tvb, swils_tree, isreq);
1578         break;
1579     case FC_SWILS_ACA:
1580         dissect_swils_aca (tvb, swils_tree, isreq);
1581         break;
1582     case FC_SWILS_RCA:
1583         dissect_swils_rca (tvb, swils_tree, isreq);
1584         break;
1585     case FC_SWILS_SFC:
1586         dissect_swils_sfc (tvb, swils_tree, isreq);
1587         break;
1588     case FC_SWILS_UFC:
1589         dissect_swils_ufc (tvb, swils_tree, isreq);
1590         break;
1591     case FC_SWILS_ESC:
1592         dissect_swils_esc (tvb, swils_tree, isreq);
1593         break;
1594     case FC_SWILS_AUTH_ILS:
1595         if (isreq && fcsp_handle) 
1596             call_dissector (fcsp_handle, tvb, pinfo, swils_tree);
1597         break;
1598     default:
1599         next_tvb = tvb_new_subset (tvb, offset+4, -1, -1);
1600         call_dissector (data_handle, next_tvb, pinfo, tree);
1601     }
1602
1603 }
1604
1605 /* Register the protocol with Ethereal */
1606
1607 /* this format is require because a script is used to build the C function
1608    that calls all the protocol registration.
1609 */
1610
1611 void
1612 proto_register_fcswils (void)
1613 {
1614 /* Setup list of header fields  See Section 1.6.1 for details*/
1615     static hf_register_info hf[] = {
1616         { &hf_swils_opcode,
1617           {"Cmd Code", "swils.opcode", FT_UINT8, BASE_HEX,
1618            VALS (fc_swils_opcode_key_val), 0x0, "", HFILL}},
1619         { &hf_swils_elp_rev,
1620           {"Revision", "swils.elp.rev", FT_UINT8, BASE_DEC, NULL,
1621            0x0, "", HFILL}},
1622         { &hf_swils_elp_flags,
1623           {"Flag", "swils.elp.flag", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL}},
1624         { &hf_swils_elp_r_a_tov,
1625           {"R_A_TOV", "swils.elp.ratov", FT_UINT32, BASE_DEC, NULL,
1626            0x0, "", HFILL}},
1627         { &hf_swils_elp_e_d_tov,
1628           {"E_D_TOV", "swils.elp.edtov", FT_UINT32, BASE_DEC, NULL, 0x0, "",
1629            HFILL}},
1630         { &hf_swils_elp_req_epn,
1631           {"Req Eport Name", "swils.elp.reqepn", FT_STRING, BASE_HEX, NULL, 0x0,
1632            "", HFILL}},
1633         { &hf_swils_elp_req_esn,
1634           {"Req Switch Name", "swils.elp.reqesn", FT_STRING, BASE_HEX, NULL, 0x0,
1635            "", HFILL}},
1636         { &hf_swils_elp_clsf_svcp,
1637           {"Class F Svc Param", "swils.elp.clsfp", FT_BYTES, BASE_NONE, NULL, 0x0,
1638            "", HFILL}},
1639         { &hf_swils_elp_clsf_rcvsz,
1640           {"Max Class F Frame Size", "swils.elp.clsfrsz", FT_UINT16, BASE_DEC,
1641            NULL, 0x0, "", HFILL}},
1642         { &hf_swils_elp_clsf_conseq,
1643           {"Class F Max Concurrent Seq", "swils.elp.clsfcs", FT_UINT16, BASE_DEC,
1644            NULL, 0x0, "", HFILL}},
1645         { &hf_swils_elp_clsf_e2e,
1646           {"Class F E2E Credit", "swils.elp.cfe2e", FT_UINT16, BASE_DEC, NULL,
1647            0x0, "", HFILL}},
1648         { &hf_swils_elp_clsf_openseq,
1649           {"Class F Max Open Seq", "swils.elp.oseq", FT_UINT16, BASE_DEC, NULL,
1650            0x0, "", HFILL}},
1651         { &hf_swils_elp_cls1_svcp,
1652           {"Class 1 Svc Param", "swils.elp.cls1p", FT_BYTES, BASE_NONE, NULL, 0x0,
1653            "", HFILL}},
1654         { &hf_swils_elp_cls1_rcvsz,
1655           {"Class 1 Frame Size", "swils.elp.cls1rsz", FT_UINT16, BASE_DEC, NULL,
1656            0x0, "", HFILL}},
1657         { &hf_swils_elp_cls2_svcp,
1658           {"Class 2 Svc Param", "swils.elp.cls2p", FT_BYTES, BASE_HEX, NULL, 0x0,
1659            "", HFILL}},
1660         { &hf_swils_elp_cls2_rcvsz,
1661           {"Class 2 Frame Size", "swils.elp.cls1rsz", FT_UINT16, BASE_DEC, NULL,
1662            0x0, "", HFILL}},
1663         { &hf_swils_elp_cls3_svcp,
1664           {"Class 3 Svc Param", "swils.elp.cls3p", FT_BYTES, BASE_HEX, NULL, 0x0,
1665            "", HFILL}},
1666         { &hf_swils_elp_cls3_rcvsz,
1667           {"Class 3 Frame Size", "swils.elp.cls1rsz", FT_UINT16, BASE_DEC, NULL,
1668            0x0, "", HFILL}},
1669         { &hf_swils_elp_isl_fc_mode,
1670           {"ISL Flow Ctrl Mode", "swils.elp.fcmode", FT_STRING, BASE_HEX, NULL,
1671            0x0, "", HFILL}},
1672         { &hf_swils_elp_fcplen,
1673           {"Flow Ctrl Param Len", "swils.elp.fcplen", FT_UINT16, BASE_DEC, NULL,
1674            0x0, "", HFILL}},
1675         { &hf_swils_elp_b2bcredit,
1676           {"B2B Credit", "swils.elp.b2b", FT_UINT32, BASE_DEC, NULL, 0x0, "",
1677            HFILL}},
1678         { &hf_swils_elp_compat1,
1679           {"Compatability Param 1", "swils.elp.compat1", FT_UINT32, BASE_DEC, NULL,
1680            0x0, "", HFILL}},
1681         { &hf_swils_elp_compat2,
1682           {"Compatability Param 2", "swils.elp.compat2", FT_UINT32, BASE_DEC, NULL,
1683            0x0, "", HFILL}},
1684         { &hf_swils_elp_compat3,
1685           {"Compatability Param 3", "swils.elp.compat3", FT_UINT32, BASE_DEC, NULL,
1686            0x0, "", HFILL}},
1687         { &hf_swils_elp_compat4,
1688           {"Compatability Param 4", "swils.elp.compat4", FT_UINT32, BASE_DEC, NULL,
1689            0x0, "", HFILL}},
1690         { &hf_swils_efp_rec_type,
1691           {"Record Type", "swils.efp.rectype", FT_UINT8, BASE_HEX,
1692            VALS (fcswils_rectype_val), 0x0, "", HFILL}},
1693         { &hf_swils_efp_dom_id,
1694           {"Domain ID", "swils.efp.domid", FT_UINT8, BASE_HEX, NULL, 0x0,
1695            "", HFILL}},
1696         { &hf_swils_efp_switch_name,
1697           {"Switch Name", "swils.efp.sname", FT_STRING, BASE_HEX, NULL, 0x0,
1698            "", HFILL}},
1699         { &hf_swils_efp_mcast_grpno,
1700           {"Mcast Grp#", "swils.efp.mcastno", FT_UINT8, BASE_HEX, NULL, 0x0,
1701            "", HFILL}},
1702         { &hf_swils_efp_alias_token,
1703           {"Alias Token", "swils.efp.aliastok", FT_BYTES, BASE_HEX, NULL, 0x0,
1704            "", HFILL}},
1705         { &hf_swils_efp_payload_len,
1706           {"Payload Len", "swils.efp.payloadlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1707            "", HFILL}},
1708         { &hf_swils_efp_pswitch_pri,
1709           {"Principal Switch Priority", "swils.efp.psprio", FT_UINT8, BASE_DEC,
1710            NULL, 0x0, "", HFILL}},
1711         { &hf_swils_efp_pswitch_name,
1712           {"Principal Switch Name", "swils.efp.psname", FT_STRING, BASE_HEX, NULL,
1713            0x0, "", HFILL}},
1714         { &hf_swils_dia_switch_name,
1715           {"Switch Name", "swils.dia.sname", FT_STRING, BASE_HEX, NULL, 0x0,
1716            "", HFILL}},
1717         { &hf_swils_rdi_payload_len,
1718           {"Payload Len", "swils.rdi.len", FT_UINT16, BASE_DEC, NULL, 0x0, "",
1719            HFILL}},
1720         { &hf_swils_rdi_req_sname,
1721           {"Req Switch Name", "swils.rdi.reqsn", FT_STRING, BASE_HEX, NULL, 0x0,
1722            "", HFILL}},
1723         { &hf_swils_fspfh_cmd,
1724           {"Command: ", "swils.fspf.cmd", FT_UINT8, BASE_HEX, NULL, 0x0,
1725            "", HFILL}},
1726         { &hf_swils_fspfh_rev,
1727           {"Version", "swils.fspf.ver", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL}},
1728         { &hf_swils_fspfh_ar_num,
1729           {"AR Number", "swils.fspf.arnum", FT_UINT8, BASE_HEX, NULL, 0x0, "",
1730            HFILL}},
1731         { &hf_swils_fspfh_auth_type,
1732           {"Authentication Type", "swils.fspf.authtype", FT_UINT8, BASE_HEX, NULL,
1733            0x0, "", HFILL}},
1734         { &hf_swils_fspfh_dom_id,
1735           {"Originating Domain ID", "swils.fspf.origdomid", FT_UINT8, BASE_DEC,
1736            NULL, 0x0, "", HFILL}},
1737         { &hf_swils_fspfh_auth,
1738           {"Authentication", "swils.fspf.auth", FT_BYTES, BASE_HEX, NULL, 0x0,
1739            "", HFILL}},
1740         { &hf_swils_hlo_options,
1741           {"Options", "swils.hlo.options", FT_BYTES, BASE_HEX, NULL, 0x0,
1742            "", HFILL}},
1743         { &hf_swils_hlo_hloint,
1744           {"Hello Interval (secs)", "swils.hlo.hloint", FT_UINT32, BASE_DEC,
1745            NULL, 0x0, "", HFILL}},
1746         { &hf_swils_hlo_deadint,
1747           {"Dead Interval (secs)", "swils.hlo.deadint", FT_UINT32, BASE_DEC,
1748            NULL, 0x0, "", HFILL}},
1749         { &hf_swils_hlo_rcv_domid,
1750           {"Recipient Domain ID", "swils.hlo.rcvdomid", FT_UINT8, BASE_DEC,
1751            NULL, 0x0, "", HFILL}},
1752         { &hf_swils_hlo_orig_pidx,
1753           {"Originating Port Idx", "swils.hlo.origpidx", FT_UINT24, BASE_HEX,
1754            NULL, 0x0, "", HFILL}},
1755         { &hf_swils_lsrh_lsr_type,
1756           {"LSR Type", "swils.lsr.type", FT_UINT8, BASE_HEX,
1757            VALS (fc_swils_fspf_linkrec_val), 0x0, "", HFILL}},
1758         { &hf_swils_lsrh_lsid,
1759           {"Link State Id", "swils.ls.id", FT_UINT8, BASE_DEC, NULL, 0x0,
1760            "", HFILL}},
1761         { &hf_swils_lsrh_adv_domid,
1762           {"Advertising Domain Id", "swils.lsr.advdomid", FT_UINT8, BASE_DEC,
1763            NULL, 0x0, "", HFILL}},
1764         { &hf_swils_lsrh_ls_incid,
1765           {"LS Incarnation Number", "swils.lsr.incid", FT_UINT32, BASE_DEC,
1766            NULL, 0x0, "", HFILL}},
1767         { &hf_swils_ldrec_linkid,
1768           {"Link ID", "swils.ldr.linkid", FT_STRING, BASE_HEX, NULL, 0x0,
1769            "", HFILL}},
1770         { &hf_swils_ldrec_out_pidx,
1771           {"Output Port Idx", "swils.ldr.out_portidx", FT_UINT24, BASE_HEX, NULL,
1772            0x0, "", HFILL}},
1773         { &hf_swils_ldrec_nbr_pidx,
1774           {"Neighbor Port Idx", "swils.ldr.nbr_portidx", FT_UINT24, BASE_HEX,
1775            NULL, 0x0, "", HFILL}},
1776         { &hf_swils_ldrec_link_type,
1777           {"Link Type", "swils.ldr.linktype", FT_UINT8, BASE_HEX,
1778            VALS (fc_swils_link_type_val), 0x0, "", HFILL}},
1779         { &hf_swils_ldrec_link_cost,
1780           {"Link Cost", "swils.ldr.linkcost", FT_UINT16, BASE_DEC, NULL, 0x0,
1781            "", HFILL}},
1782         { &hf_swils_rscn_evtype,
1783           {"Event Type", "swils.rscn.evtype", FT_UINT8, BASE_DEC,
1784            VALS (fc_swils_rscn_portstate_val), 0xF0, "", HFILL}},
1785         { &hf_swils_rscn_addrfmt,
1786           {"Address Format", "swils.rscn.addrfmt", FT_UINT8, BASE_DEC, 
1787            VALS (fc_swils_rscn_addrfmt_val), 0x0F, "", HFILL}},
1788         { &hf_swils_rscn_affectedport,
1789           {"Affected Port ID", "swils.rscn.affectedport", FT_STRING, BASE_HEX,
1790            NULL, 0x0, "", HFILL}},
1791         { &hf_swils_rscn_detectfn,
1792           {"Detection Function", "swils.rscn.detectfn", FT_UINT32, BASE_HEX,
1793            VALS (fc_swils_rscn_detectfn_val), 0x0, "", HFILL}},
1794         { &hf_swils_rscn_portstate,
1795           {"Port State", "swils.rscn.portstate", FT_UINT8, BASE_HEX, NULL, 0x0,
1796            "", HFILL}},
1797         { &hf_swils_rscn_portid,
1798           {"Port Id", "swils.rscn.portid", FT_STRING, BASE_HEX, NULL, 0x0, "",
1799            HFILL}},
1800         { &hf_swils_rscn_pwwn,
1801           {"Port WWN", "swils.rscn.pwwn", FT_STRING, BASE_HEX, NULL, 0x0, "",
1802            HFILL}},
1803         { &hf_swils_rscn_nwwn,
1804           {"Node WWN", "swils.rscn.nwwn", FT_STRING, BASE_HEX, NULL, 0x0, "",
1805            HFILL}},
1806         { &hf_swils_esc_swvendorid,
1807           {"Switch Vendor ID", "swils.esc.swvendor", FT_STRING, BASE_HEX, NULL,
1808            0x0, "", HFILL}},
1809         { &hf_swils_esc_pdesc_vendorid,
1810           {"Vendor ID", "swils.esc.vendorid", FT_STRING, BASE_HEX, NULL, 0x0,
1811            "", HFILL}},
1812         { &hf_swils_esc_protocolid,
1813           {"Protocol ID", "swils.esc.protocol", FT_UINT16, BASE_HEX,
1814            VALS (fc_swils_esc_protocol_val), 0x0, "", HFILL}},
1815         { &hf_swils_zone_activezonenm,
1816           {"Active Zoneset Name", "swils.mr.activezonesetname", FT_STRING,
1817            BASE_HEX, NULL, 0x0, "", HFILL}},
1818         { &hf_swils_zone_objname,
1819           {"Zone Object Name", "swils.zone.zoneobjname", FT_STRING, BASE_HEX,
1820            NULL, 0x0, "", HFILL}},
1821         { &hf_swils_zone_objtype,
1822           {"Zone Object Type", "swils.zone.zoneobjtype", FT_UINT8, BASE_HEX,
1823            VALS (fc_swils_zoneobj_type_val), 0x0, "", HFILL}},
1824         { &hf_swils_zone_mbrtype,
1825           {"Zone Member Type", "swils.zone.mbrtype", FT_UINT8, BASE_HEX,
1826            VALS (fc_swils_zonembr_type_val), 0x0, "", HFILL}},
1827         { &hf_swils_zone_protocol,
1828           {"Zone Protocol", "swils.zone.protocol", FT_UINT8, BASE_HEX, NULL,
1829            0x0, "", HFILL}},
1830         { &hf_swils_zone_mbrid,
1831           {"Member Identifier", "swils.zone.mbrid", FT_STRING, BASE_HEX, NULL,
1832            0x0, "", HFILL}},
1833         { &hf_swils_zone_status,
1834           {"Zone Command Status", "swils.zone.status", FT_UINT8, BASE_HEX,
1835            VALS (fc_swils_mr_rsp_val), 0x0, "Applies to MR, ACA, RCA, SFC, UFC",
1836            HFILL}},
1837         { &hf_swils_zone_reason,
1838           {"Zone Command Reason Code", "swils.zone.reason", FT_UINT8, BASE_HEX,
1839            VALS (fc_swils_mr_reason_val), 0x0, "Applies to MR, ACA, RCA, SFC, UFC",
1840            HFILL}},
1841         { &hf_swils_aca_domainid,
1842           {"Known Domain ID", "swils.aca.domainid", FT_UINT8, BASE_HEX, NULL,
1843            0x0, "", HFILL}},
1844         { &hf_swils_sfc_opcode,
1845           {"Operation Request", "swils.sfc.opcode", FT_UINT8, BASE_HEX,
1846            VALS (fc_swils_sfc_op_val), 0x0, "", HFILL}},
1847         { &hf_swils_sfc_zonenm,
1848           {"Zone Set Name", "swils.sfc.zonename", FT_STRING, BASE_HEX, NULL,
1849            0x0, "", HFILL}},
1850         { &hf_swils_rjt,
1851           {"Reason Code", "swils.rjt.reason", FT_UINT8, BASE_HEX,
1852            VALS (fc_swils_rjt_val), 0x0, "", HFILL}},
1853         { &hf_swils_rjtdet,
1854           {"Reason Code Explanantion", "swils.rjt.reasonexpl", FT_UINT8,
1855            BASE_HEX, VALS (fc_swils_deterr_val), 0x0, "", HFILL}},
1856         { &hf_swils_rjtvendor,
1857           {"Vendor Unique Error Code", "swils.rjt.vendor", FT_UINT8, BASE_HEX,
1858            NULL, 0x0, "", HFILL}},
1859         { &hf_swils_zone_mbrid_lun,
1860           {"LUN", "swils.zone.lun", FT_BYTES, BASE_HEX, NULL, 0x0, "",
1861            HFILL}},
1862     };
1863
1864     /* Setup protocol subtree array */
1865     static gint *ett[] = {
1866         &ett_fcswils,
1867         &ett_fcswils_swacc,
1868         &ett_fcswils_swrjt,
1869         &ett_fcswils_elp,
1870         &ett_fcswils_efp,
1871         &ett_fcswils_efplist,
1872         &ett_fcswils_dia,
1873         &ett_fcswils_rdi,
1874         &ett_fcswils_fspfhdr,
1875         &ett_fcswils_hlo,
1876         &ett_fcswils_lsrec,
1877         &ett_fcswils_lsrechdr,
1878         &ett_fcswils_ldrec,
1879         &ett_fcswils_lsu,
1880         &ett_fcswils_lsa,
1881         &ett_fcswils_bf,
1882         &ett_fcswils_rcf,
1883         &ett_fcswils_rscn,
1884         &ett_fcswils_rscn_dev,
1885         &ett_fcswils_drlir,
1886         &ett_fcswils_mr,
1887         &ett_fcswils_zoneobjlist,
1888         &ett_fcswils_zoneobj,
1889         &ett_fcswils_zonembr,
1890         &ett_fcswils_aca,
1891         &ett_fcswils_rca,
1892         &ett_fcswils_sfc,
1893         &ett_fcswils_ufc,
1894         &ett_fcswils_esc,
1895         &ett_fcswils_esc_pdesc,
1896     };
1897
1898     /* Register the protocol name and description */
1899     proto_fcswils = proto_register_protocol("Fibre Channel SW_ILS", "FC-SWILS", "swils");
1900
1901     /* Required function calls to register the header fields and subtrees used */
1902     proto_register_field_array(proto_fcswils, hf, array_length(hf));
1903     proto_register_subtree_array(ett, array_length(ett));
1904     register_init_routine(&fcswils_init_protocol);
1905 }
1906
1907 /* If this dissector uses sub-dissector registration add a registration routine.
1908    This format is required because a script is used to find these routines and
1909    create the code that calls these routines.
1910 */
1911 void
1912 proto_reg_handoff_fcswils (void)
1913 {
1914     dissector_handle_t swils_handle;
1915
1916     swils_handle = create_dissector_handle (dissect_fcswils, proto_fcswils);
1917     dissector_add("fc.ftype", FC_FTYPE_SWILS, swils_handle);
1918
1919     data_handle = find_dissector ("data");
1920     fcsp_handle = find_dissector ("fcsp");
1921 }
1922
1923