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