Revert "Fixup: tvb_* -> tvb_captured"
[metze/wireshark/wip.git] / epan / dissectors / packet-fcdns.c
1 /* packet-fc-dns.c
2  * Routines for FC distributed Name Server (dNS)
3  * Copyright 2001, Dinesh G Dutt <ddutt@andiamo.com>
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23
24 #define NEW_PROTO_TREE_API
25
26 #include "config.h"
27
28 #include <glib.h>
29
30 #include <epan/packet.h>
31 #include <epan/to_str.h>
32 #include <epan/wmem/wmem.h>
33 #include <epan/conversation.h>
34 #include <epan/etypes.h>
35 #include "packet-fc.h"
36 #include "packet-fcct.h"
37 #include "packet-fcdns.h"
38 #include "packet-fcswils.h"
39
40 void proto_register_fcdns(void);
41 void proto_reg_handoff_fcdns(void);
42
43 /*
44  * See FC-GS-2.
45  */
46
47 static dissector_handle_t dns_handle;
48
49 /* protocol and registered fields */
50
51 static header_field_info *hfi_fcdns = NULL;
52
53 #define FCDNS_HFI_INIT HFI_INIT(proto_fcdns)
54
55 #if 0
56 static header_field_info hfi_fcdns_gssubtype FCDNS_HFI_INIT =
57           {"GS_Subtype", "fcdns.gssubtype", FT_UINT8, BASE_HEX,
58            VALS(fc_dns_subtype_val), 0x0, NULL, HFILL};
59 #endif
60
61 static header_field_info hfi_fcdns_opcode FCDNS_HFI_INIT =
62          {"Opcode", "fcdns.opcode", FT_UINT16, BASE_HEX, VALS (fc_dns_opcode_val),
63           0x0, NULL, HFILL};
64
65 static header_field_info hfi_fcdns_reason FCDNS_HFI_INIT =
66           {"Reason Code", "fcdns.rply.reason", FT_UINT8, BASE_HEX,
67            VALS (fc_ct_rjt_code_vals), 0x0, NULL, HFILL};
68
69 static header_field_info hfi_fcdns_vendor FCDNS_HFI_INIT =
70           {"Vendor Unique Reject Code", "fcdns.rply.vendor", FT_UINT8,
71            BASE_HEX, NULL, 0x0, NULL, HFILL};
72
73 static header_field_info hfi_fcdns_req_portid FCDNS_HFI_INIT =
74           {"Port Identifier", "fcdns.req.portid", FT_STRING, BASE_NONE, NULL, 0x0,
75            NULL, HFILL};
76
77 static header_field_info hfi_fcdns_rply_pname FCDNS_HFI_INIT =
78           {"Port Name", "fcdns.rply.pname", FT_STRING, BASE_NONE, NULL, 0x0, NULL,
79            HFILL};
80
81 static header_field_info hfi_fcdns_rply_nname FCDNS_HFI_INIT =
82           {"Node Name", "fcdns.rply.nname", FT_STRING, BASE_NONE, NULL, 0x0, NULL,
83            HFILL};
84
85 static header_field_info hfi_fcdns_rply_gft FCDNS_HFI_INIT =
86           {"FC-4 Types Supported", "fcdns.rply.fc4type", FT_NONE, BASE_NONE,
87            NULL, 0x0, NULL, HFILL};
88
89 static header_field_info hfi_fcdns_rply_snamelen FCDNS_HFI_INIT =
90           {"Symbolic Node Name Length", "fcdns.rply.snamelen", FT_UINT8, BASE_DEC,
91            NULL, 0x0, NULL, HFILL};
92
93 static header_field_info hfi_fcdns_rply_sname FCDNS_HFI_INIT =
94           {"Symbolic Node Name", "fcdns.rply.sname", FT_STRING, BASE_NONE, NULL,
95            0x0, NULL, HFILL};
96
97 static header_field_info hfi_fcdns_rply_ptype FCDNS_HFI_INIT =
98           {"Port Type", "fcdns.rply.porttype", FT_UINT8, BASE_HEX,
99            VALS (fc_dns_port_type_val), 0x0, NULL, HFILL};
100
101 static header_field_info hfi_fcdns_rply_fpname FCDNS_HFI_INIT =
102           {"Fabric Port Name", "fcdns.rply.fpname", FT_STRING, BASE_NONE, NULL,
103            0x0, NULL, HFILL};
104
105 static header_field_info hfi_fcdns_fc4type FCDNS_HFI_INIT =
106           {"FC-4 Types", "fcdns.req.fc4type", FT_NONE, BASE_NONE,
107            NULL, 0x0, NULL, HFILL};
108
109 static header_field_info hfi_fcdns_rply_fc4type FCDNS_HFI_INIT =
110           {"FC-4 Descriptor Type", "fcdns.rply.fc4type", FT_UINT8, BASE_HEX,
111            VALS (fc_fc4_val), 0x0, NULL, HFILL};
112
113 static header_field_info hfi_fcdns_rply_fc4desc FCDNS_HFI_INIT =
114           {"FC-4 Descriptor", "fcdns.rply.fc4desc", FT_BYTES, BASE_NONE, NULL,
115            0x0, NULL, HFILL};
116
117 static header_field_info hfi_fcdns_req_pname FCDNS_HFI_INIT =
118           {"Port Name", "fcdns.req.portname", FT_STRING, BASE_NONE, NULL, 0x0,
119            NULL, HFILL};
120
121 static header_field_info hfi_fcdns_rply_portid FCDNS_HFI_INIT =
122           {"Port Identifier", "fcdns.rply.portid", FT_STRING, BASE_NONE, NULL,
123            0x0, NULL, HFILL};
124
125 static header_field_info hfi_fcdns_req_nname FCDNS_HFI_INIT =
126           {"Node Name", "fcdns.req.nname", FT_STRING, BASE_NONE, NULL, 0x0,
127            NULL, HFILL};
128
129 static header_field_info hfi_fcdns_req_domainscope FCDNS_HFI_INIT =
130           {"Domain ID Scope", "fcdns.req.domainid", FT_UINT8, BASE_HEX, NULL,
131            0x0, NULL, HFILL};
132
133 static header_field_info hfi_fcdns_req_areascope FCDNS_HFI_INIT =
134           {"Area ID Scope", "fcdns.req.areaid", FT_UINT8, BASE_HEX, NULL,
135            0x0, NULL, HFILL};
136
137 static header_field_info hfi_fcdns_req_ptype FCDNS_HFI_INIT =
138           {"Port Type", "fcdns.req.porttype", FT_UINT8, BASE_HEX,
139            VALS (fc_dns_port_type_val), 0x0, NULL, HFILL};
140
141 static header_field_info hfi_fcdns_req_cos FCDNS_HFI_INIT =
142           {"Requested Class of Service", "fcdns.req.class", FT_UINT32, BASE_HEX,
143            NULL, 0x0, NULL, HFILL};
144
145 static header_field_info hfi_fcdns_req_fc4types FCDNS_HFI_INIT =
146           {"FC-4 Types Supported", "fcdns.req.fc4types", FT_NONE, BASE_NONE,
147            NULL, 0x0, NULL, HFILL};
148
149 static header_field_info hfi_fcdns_req_snamelen FCDNS_HFI_INIT =
150           {"Symbolic Name Length", "fcdns.req.snamelen", FT_UINT8, BASE_DEC,
151            NULL, 0x0, NULL, HFILL};
152
153 static header_field_info hfi_fcdns_req_sname FCDNS_HFI_INIT =
154           {"Symbolic Port Name", "fcdns.req.sname", FT_STRING, BASE_NONE, NULL,
155            0x0, NULL, HFILL};
156
157 static header_field_info hfi_fcdns_rply_spnamelen FCDNS_HFI_INIT =
158           {"Symbolic Port Name Length", "fcdns.rply.spnamelen", FT_UINT8,
159            BASE_DEC, NULL, 0x0, NULL, HFILL};
160
161 static header_field_info hfi_fcdns_rply_spname FCDNS_HFI_INIT =
162          {"Symbolic Port Name", "fcdns.rply.spname", FT_STRING, BASE_NONE, NULL,
163           0x0, NULL, HFILL};
164
165 static header_field_info hfi_fcdns_req_spnamelen FCDNS_HFI_INIT =
166           {"Symbolic Port Name Length", "fcdns.req.spnamelen", FT_UINT8,
167            BASE_DEC, NULL, 0x0, NULL, HFILL};
168
169 static header_field_info hfi_fcdns_req_spname FCDNS_HFI_INIT =
170           {"Symbolic Port Name", "fcdns.req.spname", FT_STRING, BASE_NONE, NULL,
171            0x0, NULL, HFILL};
172
173 static header_field_info hfi_fcdns_rply_ipa FCDNS_HFI_INIT =
174           {"Initial Process Associator", "fcdns.rply.ipa", FT_BYTES, BASE_NONE,
175            NULL, 0x0, NULL, HFILL};
176
177 static header_field_info hfi_fcdns_rply_ipnode FCDNS_HFI_INIT =
178           {"Node IP Address", "fcdns.rply.ipnode", FT_IPv6, BASE_NONE, NULL,
179            0x0, NULL, HFILL};
180
181 static header_field_info hfi_fcdns_rply_ipport FCDNS_HFI_INIT =
182           {"Port IP Address", "fcdns.rply.ipport", FT_IPv6, BASE_NONE, NULL,
183            0x0, NULL, HFILL};
184
185 static header_field_info hfi_fcdns_rply_fc4desclen FCDNS_HFI_INIT =
186           {"FC-4 Descriptor Length", "fcdns.rply.fc4desclen", FT_UINT8,
187            BASE_DEC, NULL, 0x0, NULL, HFILL};
188
189 static header_field_info hfi_fcdns_rply_hrdaddr FCDNS_HFI_INIT =
190           {"Hard Address", "fcdns.rply.hrdaddr", FT_STRING, BASE_NONE, NULL,
191            0x0, NULL, HFILL};
192
193 static header_field_info hfi_fcdns_req_fdesclen FCDNS_HFI_INIT =
194           {"FC-4 Descriptor Length", "fcdns.req.fc4desclen", FT_UINT8, BASE_DEC,
195            NULL, 0x0, NULL, HFILL};
196
197 static header_field_info hfi_fcdns_req_fdesc FCDNS_HFI_INIT =
198           {"FC-4 Descriptor", "fcdns.req.fc4desc", FT_STRING, BASE_NONE, NULL,
199            0x0, NULL, HFILL};
200
201 static header_field_info hfi_fcdns_req_ip FCDNS_HFI_INIT =
202           {"IP Address", "fcdns.req.ip", FT_IPv6, BASE_NONE, NULL, 0x0,
203            NULL, HFILL};
204
205 static header_field_info hfi_fcdns_rjtdetail FCDNS_HFI_INIT =
206           {"Reason Code Explanantion", "fcdns.rply.reasondet", FT_UINT8,
207            BASE_HEX, VALS (fc_dns_rjt_det_code_val), 0x0, NULL, HFILL};
208
209 static header_field_info hfi_fcdns_zone_mbrtype FCDNS_HFI_INIT =
210           {"Zone Member Type", "fcdns.zone.mbrtype", FT_UINT8, BASE_HEX,
211            VALS (fc_swils_zonembr_type_val), 0x0, NULL, HFILL};
212
213 static header_field_info hfi_fcdns_zone_mbrid FCDNS_HFI_INIT =
214           {"Member Identifier", "fcdns.zone.mbrid", FT_STRING, BASE_NONE, NULL,
215            0x0, NULL, HFILL};
216
217 static header_field_info hfi_fcdns_zonenm FCDNS_HFI_INIT =
218           {"Zone Name", "fcdns.zonename", FT_STRING, BASE_NONE, NULL, 0x0, NULL,
219            HFILL};
220
221 static header_field_info hfi_fcdns_portip FCDNS_HFI_INIT =
222           {"Port IP Address", "fcdns.portip", FT_IPv4, BASE_NONE, NULL, 0x0,
223            NULL, HFILL};
224
225 static header_field_info hfi_fcdns_sw2_objfmt FCDNS_HFI_INIT =
226           {"Name Entry Object Format", "fcdns.entry.objfmt", FT_UINT8, BASE_HEX,
227            NULL, 0x0, NULL, HFILL};
228
229 static header_field_info hfi_fcdns_num_fc4desc FCDNS_HFI_INIT =
230           {"Number of FC4 Descriptors Registered", "fcdns.entry.numfc4desc",
231            FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL};
232
233 static header_field_info hfi_fcdns_rply_ownerid FCDNS_HFI_INIT =
234           {"Owner Id", "fcdns.rply.ownerid", FT_STRING, BASE_NONE, NULL, 0x0, NULL,
235            HFILL};
236
237 static header_field_info hfi_fcdns_maxres_size FCDNS_HFI_INIT =
238           {"Maximum/Residual Size", "fcdns.maxres_size", FT_UINT16, BASE_DEC,
239            NULL, 0x0, NULL, HFILL};
240
241 static header_field_info hfi_fcdns_reply_cos FCDNS_HFI_INIT =
242           {"Class of Service Supported", "fcdns.reply.cos", FT_UINT32, BASE_HEX,
243            NULL, 0x0, NULL, HFILL};
244
245 static header_field_info hfi_fcdns_cos_f FCDNS_HFI_INIT =
246           {"F", "fcdns.cos.f", FT_BOOLEAN, 32,
247            TFS(&tfs_set_notset), 0x01, NULL, HFILL};
248
249 static header_field_info hfi_fcdns_cos_1 FCDNS_HFI_INIT =
250           {"1", "fcdns.cos.1", FT_BOOLEAN, 32,
251            TFS(&tfs_set_notset), 0x02, NULL, HFILL};
252
253 static header_field_info hfi_fcdns_cos_2 FCDNS_HFI_INIT =
254           {"2", "fcdns.cos.2", FT_BOOLEAN, 32,
255            TFS(&tfs_set_notset), 0x04, NULL, HFILL};
256
257 static header_field_info hfi_fcdns_cos_3 FCDNS_HFI_INIT =
258           {"3", "fcdns.cos.3", FT_BOOLEAN, 32,
259            TFS(&tfs_set_notset), 0x08, NULL, HFILL};
260
261 static header_field_info hfi_fcdns_cos_4 FCDNS_HFI_INIT =
262           {"4", "fcdns.cos.4", FT_BOOLEAN, 32,
263            TFS(&tfs_set_notset), 0x10, NULL, HFILL};
264
265 static header_field_info hfi_fcdns_cos_6 FCDNS_HFI_INIT =
266           {"6", "fcdns.cos.6", FT_BOOLEAN, 32,
267            TFS(&tfs_set_notset), 0x40, NULL, HFILL};
268
269 static header_field_info hfi_fcdns_fc4type_llcsnap FCDNS_HFI_INIT =
270           {"LLC/SNAP", "fcdns.fc4types.llc_snap", FT_BOOLEAN, 32,
271            TFS(&tfs_set_notset), 0x0010, NULL, HFILL};
272
273 static header_field_info hfi_fcdns_fc4type_ip FCDNS_HFI_INIT =
274           {"IP", "fcdns.fc4types.ip", FT_BOOLEAN, 32,
275            TFS(&tfs_set_notset), 0x0020, NULL, HFILL};
276
277 static header_field_info hfi_fcdns_fc4type_fcp FCDNS_HFI_INIT =
278           {"FCP", "fcdns.fc4types.fcp", FT_BOOLEAN, 32,
279            TFS(&tfs_set_notset), 0x0100, NULL, HFILL};
280
281 static header_field_info hfi_fcdns_fc4type_swils FCDNS_HFI_INIT =
282           {"SW_ILS", "fcdns.fc4types.swils", FT_BOOLEAN, 32,
283            TFS(&tfs_set_notset), 0x0010, NULL, HFILL};
284
285 static header_field_info hfi_fcdns_fc4type_snmp FCDNS_HFI_INIT =
286           {"SNMP", "fcdns.fc4types.snmp", FT_BOOLEAN, 32,
287            TFS(&tfs_set_notset), 0x0004, NULL, HFILL};
288
289 static header_field_info hfi_fcdns_fc4type_gs3 FCDNS_HFI_INIT =
290           {"GS3", "fcdns.fc4types.gs3", FT_BOOLEAN, 32,
291            TFS(&tfs_set_notset), 0x0001, NULL, HFILL};
292
293 static header_field_info hfi_fcdns_fc4type_vi FCDNS_HFI_INIT =
294           {"VI", "fcdns.fc4types.vi", FT_BOOLEAN, 32,
295            TFS(&tfs_set_notset), 0x0001, NULL, HFILL};
296
297 static header_field_info hfi_fcdns_fc4features FCDNS_HFI_INIT =
298           {"FC-4 Feature Bits", "fcdns.fc4features", FT_UINT8,
299            BASE_HEX, NULL, 0x0, NULL, HFILL};
300
301 static header_field_info hfi_fcdns_fc4features_i FCDNS_HFI_INIT =
302           {"I", "fcdns.fc4features.i", FT_BOOLEAN, 8,
303            TFS(&tfs_set_notset), 0x02, NULL, HFILL};
304
305 static header_field_info hfi_fcdns_fc4features_t FCDNS_HFI_INIT =
306           {"T", "fcdns.fc4features.t", FT_BOOLEAN, 8,
307            TFS(&tfs_set_notset), 0x01, NULL, HFILL};
308
309 static header_field_info hfi_fcdns_req_fc4type FCDNS_HFI_INIT =
310           {"FC-4 Type", "fcdns.req.fc4type", FT_UINT8, BASE_HEX,
311            VALS (fc_fc4_val), 0x0, NULL, HFILL};
312
313
314 /* Initialize the subtree pointers */
315 static gint ett_fcdns = -1;
316 static gint ett_cos_flags = -1;
317 static gint ett_fc4flags = -1;
318 static gint ett_fc4features = -1;
319
320 typedef struct _fcdns_conv_key {
321     guint32 conv_idx;
322 } fcdns_conv_key_t;
323
324 typedef struct _fcdns_conv_data {
325     guint32 opcode;
326 } fcdns_conv_data_t;
327
328 static GHashTable *fcdns_req_hash = NULL;
329
330 /*
331  * Hash Functions
332  */
333 static gint
334 fcdns_equal(gconstpointer v, gconstpointer w)
335 {
336   const fcdns_conv_key_t *v1 = (const fcdns_conv_key_t *)v;
337   const fcdns_conv_key_t *v2 = (const fcdns_conv_key_t *)w;
338
339   return (v1->conv_idx == v2->conv_idx);
340 }
341
342 static guint
343 fcdns_hash (gconstpointer v)
344 {
345     const fcdns_conv_key_t *key = (const fcdns_conv_key_t *)v;
346     guint val;
347
348     val = key->conv_idx;
349
350     return val;
351 }
352
353 /*
354  * Protocol initialization
355  */
356 static void
357 fcdns_init_protocol(void)
358 {
359     if (fcdns_req_hash)
360         g_hash_table_destroy(fcdns_req_hash);
361
362     fcdns_req_hash = g_hash_table_new(fcdns_hash, fcdns_equal);
363 }
364
365
366 static void
367 dissect_cos_flags (proto_tree *parent_tree, tvbuff_t *tvb, int offset, const header_field_info *hfinfo)
368 {
369     proto_item *item=NULL;
370     proto_tree *tree=NULL;
371     guint32 flags;
372
373     flags = tvb_get_ntohl (tvb, offset);
374     if(parent_tree){
375         item=proto_tree_add_uint(parent_tree, hfinfo,
376                                  tvb, offset, 1, flags);
377         tree=proto_item_add_subtree(item, ett_cos_flags);
378     }
379
380
381     proto_tree_add_boolean(tree, &hfi_fcdns_cos_f, tvb, offset, 4, flags);
382     if (flags&0x01){
383         proto_item_append_text(item, "  F");
384     }
385     flags&=(~( 0x01 ));
386
387     proto_tree_add_boolean(tree, &hfi_fcdns_cos_1, tvb, offset, 4, flags);
388     if (flags&0x02){
389         proto_item_append_text(item, "  1");
390     }
391     flags&=(~( 0x02 ));
392
393     proto_tree_add_boolean(tree, &hfi_fcdns_cos_2, tvb, offset, 4, flags);
394     if (flags&0x04){
395         proto_item_append_text(item, "  2");
396     }
397     flags&=(~( 0x04 ));
398
399     proto_tree_add_boolean(tree, &hfi_fcdns_cos_3, tvb, offset, 4, flags);
400     if (flags&0x08){
401         proto_item_append_text(item, "  3");
402     }
403     flags&=(~( 0x08 ));
404
405     proto_tree_add_boolean(tree, &hfi_fcdns_cos_4, tvb, offset, 4, flags);
406     if (flags&0x10){
407         proto_item_append_text(item, "  4");
408     }
409     flags&=(~( 0x10 ));
410
411     proto_tree_add_boolean(tree, &hfi_fcdns_cos_6, tvb, offset, 4, flags);
412     if (flags&0x40){
413         proto_item_append_text(item, "  6");
414     }
415     /*flags&=(~( 0x40 ));*/
416 }
417
418
419
420 /* The feature routines just decode FCP's FC-4 features field
421  * based on the flahs in offset and the type in offset+1
422  */
423 static void
424 dissect_fc4features_and_type (proto_tree *parent_tree, tvbuff_t *tvb, int offset)
425 {
426     proto_item *item=NULL;
427     proto_tree *tree=NULL;
428     guint8 flags, type;
429
430     flags = tvb_get_guint8(tvb, offset);
431     type = tvb_get_guint8(tvb, offset+1);
432     if(parent_tree){
433         item=proto_tree_add_uint(parent_tree, &hfi_fcdns_fc4features,
434                                  tvb, offset, 1, flags);
435         tree=proto_item_add_subtree(item, ett_fc4features);
436     }
437
438     if(type==FC_TYPE_SCSI){
439         proto_tree_add_boolean(tree, &hfi_fcdns_fc4features_i, tvb, offset, 1, flags);
440         if (flags&0x02){
441             proto_item_append_text(item, "  I");
442         }
443         flags&=(~( 0x02 ));
444
445         proto_tree_add_boolean(tree, &hfi_fcdns_fc4features_t, tvb, offset, 1, flags);
446         if (flags&0x01){
447             proto_item_append_text(item, "  T");
448         }
449         /*flags&=(~( 0x01 ));*/
450     }
451
452     proto_tree_add_item (tree, &hfi_fcdns_req_fc4type, tvb, offset+1, 1, ENC_BIG_ENDIAN);
453 }
454
455 /* The feature routines just decode FCP's FC-4 features field
456  */
457 static void
458 dissect_fc4features (proto_tree *parent_tree, tvbuff_t *tvb, int offset)
459 {
460     proto_item *item=NULL;
461     proto_tree *tree=NULL;
462     guint8 flags;
463
464     flags = tvb_get_guint8(tvb, offset);
465     if(parent_tree){
466         item=proto_tree_add_uint(parent_tree, &hfi_fcdns_fc4features,
467                                  tvb, offset, 1, flags);
468         tree=proto_item_add_subtree(item, ett_fc4features);
469     }
470
471     proto_tree_add_boolean(tree, &hfi_fcdns_fc4features_i, tvb, offset, 1, flags);
472     if (flags&0x02){
473         proto_item_append_text(item, "  I");
474     }
475     flags&=(~( 0x02 ));
476
477     proto_tree_add_boolean(tree, &hfi_fcdns_fc4features_t, tvb, offset, 1, flags);
478     if (flags&0x01){
479         proto_item_append_text(item, "  T");
480     }
481     /*flags&=(~( 0x01 ));*/
482 }
483
484
485
486 /* Decodes LLC/SNAP, IP, FCP, VI, GS, SW_ILS types only */
487 static void
488 dissect_fc4type (proto_tree *parent_tree, tvbuff_t *tvb, int offset, header_field_info *hfinfo)
489 {
490     proto_item *item=NULL;
491     proto_tree *tree=NULL;
492     guint32 flags;
493
494     if(parent_tree){
495         item=proto_tree_add_item(parent_tree, hfinfo, tvb, offset,
496                                  32, ENC_NA);
497         tree=proto_item_add_subtree(item, ett_fc4flags);
498     }
499
500     flags = tvb_get_ntohl (tvb, offset);
501
502     proto_tree_add_boolean(tree, &hfi_fcdns_fc4type_fcp, tvb, offset, 4, flags);
503     if (flags&0x0100){
504         proto_item_append_text(item, "  FCP");
505     }
506     flags&=(~( 0x0100 ));
507
508     proto_tree_add_boolean(tree, &hfi_fcdns_fc4type_ip, tvb, offset, 4, flags);
509     if (flags&0x0020){
510         proto_item_append_text(item, "  IP");
511     }
512     flags&=(~( 0x0020 ));
513
514     proto_tree_add_boolean(tree, &hfi_fcdns_fc4type_llcsnap, tvb, offset, 4, flags);
515     if (flags&0x0010){
516         proto_item_append_text(item, "  LLC/SNAP");
517     }
518     /*flags&=(~( 0x0010 ));*/
519
520
521     flags = tvb_get_ntohl (tvb, offset+4);
522
523     proto_tree_add_boolean(tree, &hfi_fcdns_fc4type_swils, tvb, offset+4, 4, flags);
524     if (flags&0x0010){
525         proto_item_append_text(item, "  SW_ILS");
526     }
527     flags&=(~( 0x0010 ));
528
529     proto_tree_add_boolean(tree, &hfi_fcdns_fc4type_snmp, tvb, offset+4, 4, flags);
530     if (flags&0x0004){
531         proto_item_append_text(item, "  SNMP");
532     }
533     flags&=(~( 0x0004 ));
534
535     proto_tree_add_boolean(tree, &hfi_fcdns_fc4type_gs3, tvb, offset+4, 4, flags);
536     if (flags&0x0001){
537         proto_item_append_text(item, "  GS3");
538     }
539     /*flags&=(~( 0x0001 ));*/
540
541
542     flags = tvb_get_ntohl (tvb, offset+8);
543
544     proto_tree_add_boolean(tree, &hfi_fcdns_fc4type_vi, tvb, offset+8, 4, flags);
545     if (flags&0x0001){
546         proto_item_append_text(item, "  VI");
547     }
548     /*flags&=(~( 0x0001 ));*/
549 }
550
551 /* Code to actually dissect the packets */
552
553 /* A bunch of get routines have a similar req packet format. The first few
554  * routines deal with this decoding. All assume that tree is valid */
555 static void
556 dissect_fcdns_req_portid (tvbuff_t *tvb, proto_tree *tree, int offset)
557 {
558     if (tree) {
559         proto_tree_add_string (tree, &hfi_fcdns_req_portid, tvb, offset, 3,
560                                tvb_fc_to_str (tvb, offset));
561     }
562 }
563
564 static void
565 dissect_fcdns_ganxt (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
566 {
567     int offset = 16;            /* past the fc_ct header */
568     guint8 len;
569
570     if (req_tree) {
571         if (isreq) {
572             dissect_fcdns_req_portid (tvb, req_tree, offset+1);
573         }
574         else {
575             proto_tree_add_item (req_tree, &hfi_fcdns_rply_ptype, tvb, offset,
576                                  1, ENC_BIG_ENDIAN);
577             proto_tree_add_string (req_tree, &hfi_fcdns_rply_portid, tvb,
578                                    offset+1, 3,
579                                    tvb_fc_to_str (tvb, offset+1));
580             proto_tree_add_string (req_tree, &hfi_fcdns_rply_pname, tvb,
581                                    offset+4, 8,
582                                    tvb_fcwwn_to_str (tvb, offset+4));
583             len = tvb_get_guint8 (tvb, offset+12);
584             proto_tree_add_item (req_tree, &hfi_fcdns_rply_spnamelen, tvb,
585                                  offset+12, 1, ENC_BIG_ENDIAN);
586             if (!tvb_offset_exists (tvb, 29+len))
587                 return;
588
589             if (len) {
590                 proto_tree_add_item (req_tree, &hfi_fcdns_rply_spname, tvb,
591                                      offset+13, len, ENC_ASCII|ENC_NA);
592             }
593
594             if (tvb_offset_exists (tvb, 292)) {
595                 proto_tree_add_string (req_tree, &hfi_fcdns_rply_nname, tvb,
596                                        offset+268, 8,
597                                        tvb_fcwwn_to_str (tvb, offset+268));
598             }
599             if (tvb_offset_exists (tvb, 548)) {
600                 len = tvb_get_guint8 (tvb, offset+276);
601                 proto_tree_add_item (req_tree, &hfi_fcdns_rply_snamelen, tvb,
602                                      offset+276, 1, ENC_BIG_ENDIAN);
603                 if (len) {
604                     proto_tree_add_item (req_tree, &hfi_fcdns_rply_sname, tvb,
605                                          offset+277, len, ENC_ASCII|ENC_NA);
606                 }
607             }
608             if (tvb_offset_exists (tvb, 556)) {
609                 proto_tree_add_item (req_tree, &hfi_fcdns_rply_ipa, tvb,
610                                      offset+532, 8, ENC_NA);
611             }
612             if (tvb_offset_exists (tvb, 572)) {
613                 proto_tree_add_item (req_tree, &hfi_fcdns_rply_ipnode, tvb,
614                                      offset+540, 16, ENC_NA);
615             }
616             if (tvb_offset_exists (tvb, 576)) {
617                 dissect_cos_flags(req_tree, tvb, offset+556, &hfi_fcdns_reply_cos);
618             }
619             if (tvb_offset_exists (tvb, 608)) {
620                 dissect_fc4type(req_tree, tvb, offset+560, &hfi_fcdns_rply_gft);
621             }
622             if (tvb_offset_exists (tvb, 624)) {
623                 proto_tree_add_item (req_tree, &hfi_fcdns_rply_ipport, tvb,
624                                      offset+592, 16, ENC_NA);
625             }
626             if (tvb_offset_exists (tvb, 632)) {
627                 proto_tree_add_string (req_tree, &hfi_fcdns_rply_fpname, tvb,
628                                        offset+608, 8,
629                                        tvb_fcwwn_to_str (tvb, offset+608));
630             }
631             if (tvb_offset_exists (tvb, 635)) {
632                 proto_tree_add_string (req_tree, &hfi_fcdns_rply_hrdaddr, tvb,
633                                        offset+617, 3,
634                                        tvb_fc_to_str (tvb, offset+617));
635             }
636         }
637     }
638 }
639
640 static void
641 dissect_fcdns_gpnid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
642 {
643     int offset = 16;            /* past the fc_ct header */
644
645     if (req_tree) {
646         if (isreq) {
647             dissect_fcdns_req_portid (tvb, req_tree, offset+1);
648         }
649         else {
650             proto_tree_add_string (req_tree, &hfi_fcdns_rply_pname, tvb, offset,
651                                    8, tvb_fcwwn_to_str (tvb, offset));
652         }
653     }
654 }
655
656 static void
657 dissect_fcdns_gnnid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
658 {
659     int offset = 16;            /* past the fc_ct header */
660
661     if (req_tree) {
662         if (isreq) {
663             dissect_fcdns_req_portid (tvb, req_tree, offset+1);
664         }
665         else {
666             proto_tree_add_string (req_tree, &hfi_fcdns_rply_nname, tvb,
667                                    offset, 8,
668                                    tvb_fcwwn_to_str (tvb, offset));
669         }
670     }
671 }
672
673 static void
674 dissect_fcdns_gcsid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
675 {
676     int offset = 16;            /* past the fc_ct header */
677
678     if (req_tree) {
679         if (isreq) {
680             dissect_fcdns_req_portid (tvb, req_tree, offset);
681         }
682         else {
683             dissect_cos_flags(req_tree, tvb, offset, &hfi_fcdns_reply_cos);
684         }
685     }
686 }
687
688 static void
689 dissect_fcdns_gftid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
690 {
691     int offset = 16;            /* past the fc_ct header */
692
693     if (req_tree) {
694         if (isreq) {
695             dissect_fcdns_req_portid (tvb, req_tree, offset+1);
696         }
697         else {
698             dissect_fc4type(req_tree, tvb, offset, &hfi_fcdns_rply_gft);
699         }
700     }
701 }
702
703 static void
704 dissect_fcdns_gspnid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
705 {
706     int offset = 16;            /* past the fc_ct header */
707     guint8 len;
708
709     if (req_tree) {
710         if (isreq) {
711             dissect_fcdns_req_portid (tvb, req_tree, offset+1);
712         }
713         else {
714             len = tvb_get_guint8 (tvb, offset);
715             proto_tree_add_item (req_tree, &hfi_fcdns_rply_spnamelen,
716                                  tvb, offset, 1, ENC_BIG_ENDIAN);
717             proto_tree_add_item (req_tree, &hfi_fcdns_rply_spname, tvb,
718                                  offset+1, len, ENC_ASCII|ENC_NA);
719         }
720     }
721 }
722
723 static void
724 dissect_fcdns_gptid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
725 {
726     int offset = 16;            /* past the fc_ct header */
727
728     if (req_tree) {
729         if (isreq) {
730             dissect_fcdns_req_portid (tvb, req_tree, offset+1);
731         }
732         else {
733             proto_tree_add_item (req_tree, &hfi_fcdns_rply_ptype, tvb,
734                                  offset, 1, ENC_BIG_ENDIAN);
735         }
736     }
737 }
738
739 static void
740 dissect_fcdns_gfpnid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
741 {
742     int offset = 16;            /* past the fc_ct header */
743
744     if (req_tree) {
745         if (isreq) {
746             dissect_fcdns_req_portid (tvb, req_tree, offset+1);
747         }
748         else {
749             proto_tree_add_string (req_tree, &hfi_fcdns_rply_fpname, tvb,
750                                    offset, 8,
751                                    tvb_fcwwn_to_str (tvb, offset));
752         }
753     }
754
755 }
756
757 static void
758 dissect_fcdns_gfdid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
759 {
760     int offset = 16;            /* past the fc_ct header */
761     int tot_len, desclen;
762
763     if (req_tree) {
764         if (isreq) {
765             dissect_fcdns_req_portid (tvb, req_tree, offset+1);
766             dissect_fc4type(req_tree, tvb, offset+4, &hfi_fcdns_fc4type);
767         }
768         else {
769             tot_len = tvb_reported_length_remaining (tvb, offset); /* excluding CT header */
770             while (tot_len > 0) {
771                 /* The count of the descriptors is not returned and so we have
772                  * to track the display by the length field */
773                 desclen = tvb_get_guint8 (tvb, offset);
774                 proto_tree_add_item (req_tree, &hfi_fcdns_rply_fc4desc, tvb,
775                                      offset, desclen, ENC_NA);
776                 tot_len -= 255; /* descriptors are aligned to 255 bytes */
777                 offset += 256;
778             }
779         }
780     }
781 }
782
783 static void
784 dissect_fcdns_gffid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
785 {
786     int offset = 16;            /* past the fc_ct header */
787
788     if (req_tree) {
789         if (isreq) {
790             dissect_fcdns_req_portid (tvb, req_tree, offset+1);
791         }
792         else {
793             dissect_fc4features(req_tree, tvb, offset);
794         }
795     }
796 }
797
798 static void
799 dissect_fcdns_gidpn (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
800 {
801     int offset = 16;            /* past the fc_ct header */
802
803     if (req_tree) {
804         if (isreq) {
805             proto_tree_add_string (req_tree, &hfi_fcdns_req_pname, tvb,
806                                    offset, 8,
807                                    tvb_fcwwn_to_str (tvb, offset));
808         }
809         else {
810             proto_tree_add_string (req_tree, &hfi_fcdns_rply_portid, tvb,
811                                    offset+1, 3,
812                                    tvb_fc_to_str (tvb, offset+1));
813         }
814     }
815 }
816
817 static void
818 dissect_fcdns_gipppn (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
819 {
820     int offset = 16;            /* past the fc_ct header */
821
822     if (req_tree) {
823         if (isreq) {
824             proto_tree_add_string (req_tree, &hfi_fcdns_req_pname, tvb,
825                                    offset, 8,
826                                    tvb_fcwwn_to_str (tvb, offset));
827         }
828         else {
829             proto_tree_add_item (req_tree, &hfi_fcdns_rply_ipport, tvb, offset,
830                                  16, ENC_NA);
831         }
832     }
833 }
834
835 static void
836 dissect_fcdns_gidnn (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
837 {
838     int offset = 16;            /* past the fc_ct header */
839     guint8 islast;
840
841     if (req_tree) {
842         if (isreq) {
843             proto_tree_add_string (req_tree, &hfi_fcdns_req_nname, tvb,
844                                    offset, 8,
845                                    tvb_fcwwn_to_str (tvb, offset));
846         }
847         else {
848             do {
849                 islast = tvb_get_guint8 (tvb, offset);
850                 proto_tree_add_string (req_tree, &hfi_fcdns_rply_portid,
851                                        tvb, offset+1, 3,
852                                        tvb_fc_to_str (tvb, offset+1));
853                 offset += 4;
854             } while (!(islast & 0x80));
855         }
856     }
857 }
858
859 static void
860 dissect_fcdns_gipnn (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
861 {
862     int offset = 16;            /* past the fc_ct header */
863
864     if (req_tree) {
865         if (isreq) {
866             proto_tree_add_string (req_tree, &hfi_fcdns_req_nname, tvb,
867                                    offset, 8,
868                                    tvb_fcwwn_to_str (tvb, offset));
869         }
870         else {
871             proto_tree_add_item (req_tree, &hfi_fcdns_rply_ipnode, tvb, offset,
872                                  16, ENC_NA);
873         }
874     }
875 }
876
877 static void
878 dissect_fcdns_gpnnn (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
879 {
880     int offset = 16;            /* past the fc_ct header */
881     guint8 islast;
882
883     if (req_tree) {
884         if (isreq) {
885             proto_tree_add_string (req_tree, &hfi_fcdns_req_nname, tvb,
886                                    offset, 8,
887                                    tvb_fcwwn_to_str (tvb, offset));
888         }
889         else {
890             do {
891                 islast = tvb_get_guint8 (tvb, offset);
892                 proto_tree_add_string (req_tree, &hfi_fcdns_rply_portid,
893                                        tvb, offset+1, 3,
894                                        tvb_fc_to_str (tvb, offset+1));
895                 proto_tree_add_string (req_tree, &hfi_fcdns_rply_pname,
896                                        tvb, offset+8, 8,
897                                        tvb_fcwwn_to_str (tvb, offset+8));
898                 offset += 16;
899             } while (!(islast & 0x80));
900         }
901     }
902 }
903
904 static void
905 dissect_fcdns_gsnnnn (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
906 {
907     int offset = 16;            /* past the fc_ct header */
908     guint8 len;
909
910     if (req_tree) {
911         if (isreq) {
912             proto_tree_add_string (req_tree, &hfi_fcdns_req_nname, tvb,
913                                    offset, 8,
914                                    tvb_fcwwn_to_str (tvb, offset));
915         }
916         else {
917             len = tvb_get_guint8 (tvb, offset);
918             proto_tree_add_item (req_tree, &hfi_fcdns_rply_snamelen, tvb,
919                                  offset, 1, ENC_BIG_ENDIAN);
920             proto_tree_add_item (req_tree, &hfi_fcdns_rply_sname, tvb,
921                                  offset+1, len, ENC_ASCII|ENC_NA);
922         }
923     }
924 }
925
926 static void
927 dissect_fcdns_gidft (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
928 {
929     int offset = 16;            /* past the fc_ct header */
930     guint8 islast;
931
932     if (req_tree) {
933         if (isreq) {
934             proto_tree_add_item (req_tree, &hfi_fcdns_req_domainscope,
935                                  tvb, offset+1, 1, ENC_BIG_ENDIAN);
936             proto_tree_add_item (req_tree, &hfi_fcdns_req_areascope,
937                                  tvb, offset+2, 1, ENC_BIG_ENDIAN);
938             proto_tree_add_item (req_tree, &hfi_fcdns_req_fc4type,
939                                  tvb, offset+3, 1, ENC_BIG_ENDIAN);
940         }
941         else {
942             do {
943                 islast = tvb_get_guint8 (tvb, offset);
944                 proto_tree_add_string (req_tree, &hfi_fcdns_rply_portid,
945                                        tvb, offset+1, 3,
946                                        tvb_fc_to_str (tvb, offset+1));
947                 offset += 4;
948             } while (!(islast & 0x80));
949         }
950     }
951 }
952
953 static void
954 dissect_fcdns_gpnft (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
955 {
956     int offset = 16;            /* past the fc_ct header */
957     guint8 islast;
958
959     if (req_tree) {
960         if (isreq) {
961             proto_tree_add_item (req_tree, &hfi_fcdns_req_domainscope,
962                                  tvb, offset+1, 1, ENC_BIG_ENDIAN);
963             proto_tree_add_item (req_tree, &hfi_fcdns_req_areascope,
964                                  tvb, offset+2, 1, ENC_BIG_ENDIAN);
965             proto_tree_add_item (req_tree, &hfi_fcdns_req_fc4type,
966                                  tvb, offset+3, 1, ENC_BIG_ENDIAN);
967         }
968         else {
969             do {
970                 islast = tvb_get_guint8 (tvb, offset);
971                 proto_tree_add_string (req_tree, &hfi_fcdns_rply_portid,
972                                        tvb, offset+1, 3,
973                                        tvb_fc_to_str (tvb, offset+1));
974                 proto_tree_add_string (req_tree, &hfi_fcdns_rply_pname,
975                                        tvb, offset+4, 8,
976                                        tvb_fcwwn_to_str (tvb, offset+8));
977                 offset += 16;
978             } while (!(islast & 0x80));
979         }
980     }
981 }
982
983 static void
984 dissect_fcdns_gnnft (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
985 {
986     int offset = 16;            /* past the fc_ct header */
987     guint8 islast;
988
989     if (req_tree) {
990         if (isreq) {
991             proto_tree_add_item (req_tree, &hfi_fcdns_req_domainscope,
992                                  tvb, offset+1, 1, ENC_BIG_ENDIAN);
993             proto_tree_add_item (req_tree, &hfi_fcdns_req_areascope,
994                                  tvb, offset+2, 1, ENC_BIG_ENDIAN);
995             proto_tree_add_item (req_tree, &hfi_fcdns_req_fc4type,
996                                  tvb, offset+3, 1, ENC_BIG_ENDIAN);
997         }
998         else {
999             do {
1000                 islast = tvb_get_guint8 (tvb, offset);
1001                 proto_tree_add_string (req_tree, &hfi_fcdns_rply_portid,
1002                                        tvb, offset+1, 3,
1003                                        tvb_fc_to_str (tvb, offset+1));
1004                 proto_tree_add_string (req_tree, &hfi_fcdns_rply_nname,
1005                                        tvb, offset+4, 8,
1006                                        tvb_fcwwn_to_str (tvb, offset+8));
1007                 offset += 16;
1008             } while (!(islast & 0x80));
1009         }
1010     }
1011 }
1012
1013 static void
1014 dissect_fcdns_gidpt (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
1015 {
1016     int offset = 16;            /* past the fc_ct header */
1017     guint8 islast = 0;
1018
1019     if (req_tree) {
1020         if (isreq) {
1021             proto_tree_add_item (req_tree, &hfi_fcdns_req_ptype,
1022                                  tvb, offset, 1, ENC_BIG_ENDIAN);
1023             proto_tree_add_item (req_tree, &hfi_fcdns_req_domainscope,
1024                                  tvb, offset+1, 1, ENC_BIG_ENDIAN);
1025             proto_tree_add_item (req_tree, &hfi_fcdns_req_areascope,
1026                                  tvb, offset+2, 1, ENC_BIG_ENDIAN);
1027         }
1028         else {
1029             do {
1030                 islast = tvb_get_guint8 (tvb, offset);
1031                 proto_tree_add_string (req_tree, &hfi_fcdns_rply_portid,
1032                                        tvb, offset+1, 3,
1033                                        tvb_fc_to_str (tvb, offset+1));
1034                 offset += 4;
1035             } while (!(islast & 0x80));
1036         }
1037     }
1038 }
1039
1040 static void
1041 dissect_fcdns_gidipp (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
1042 {
1043     int offset = 16;            /* past the fc_ct header */
1044     guint8 islast;
1045
1046     if (req_tree) {
1047         if (isreq) {
1048             proto_tree_add_item (req_tree, &hfi_fcdns_req_ip, tvb, offset,
1049                                  16, ENC_NA);
1050         }
1051         else {
1052             do {
1053                 islast = tvb_get_guint8 (tvb, offset);
1054                 proto_tree_add_string (req_tree, &hfi_fcdns_rply_portid,
1055                                        tvb, offset+1, 3,
1056                                        tvb_fc_to_str (tvb, offset+1));
1057                 offset += 4;
1058             } while (!(islast & 0x80));
1059         }
1060     }
1061 }
1062
1063 static void
1064 dissect_fcdns_gidff (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
1065 {
1066     int offset = 16;            /* past the fc_ct header */
1067     guint8 islast;
1068
1069     if (req_tree) {
1070         if (isreq) {
1071             proto_tree_add_item (req_tree, &hfi_fcdns_req_domainscope, tvb,
1072                                  offset+1, 1, ENC_BIG_ENDIAN);
1073             proto_tree_add_item (req_tree, &hfi_fcdns_req_areascope, tvb,
1074                                  offset+2, 1, ENC_BIG_ENDIAN);
1075             dissect_fc4features_and_type(req_tree, tvb, offset+6);
1076         }
1077         else {
1078             do {
1079                 islast = tvb_get_guint8 (tvb, offset);
1080                 proto_tree_add_string (req_tree, &hfi_fcdns_rply_portid,
1081                                        tvb, offset+1, 3,
1082                                        tvb_fc_to_str (tvb, offset+1));
1083                 offset += 4;
1084             } while (!(islast & 0x80));
1085         }
1086     }
1087 }
1088
1089 static void
1090 dissect_fcdns_rpnid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
1091 {
1092     int offset = 16;            /* past the fc_ct header */
1093
1094     if (req_tree) {
1095         if (isreq) {
1096             proto_tree_add_string (req_tree, &hfi_fcdns_req_portid,
1097                                    tvb, offset+1, 3,
1098                                    tvb_fc_to_str (tvb, offset+1));
1099             proto_tree_add_string (req_tree, &hfi_fcdns_req_pname, tvb,
1100                                    offset+4, 8,
1101                                    tvb_fcwwn_to_str (tvb, offset+4));
1102         }
1103     }
1104 }
1105
1106 static void
1107 dissect_fcdns_rnnid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
1108 {
1109     int offset = 16;            /* past the fc_ct header */
1110
1111     if (req_tree) {
1112         if (isreq) {
1113             proto_tree_add_string (req_tree, &hfi_fcdns_req_portid,
1114                                    tvb, offset+1, 3,
1115                                    tvb_fc_to_str (tvb, offset+1));
1116             proto_tree_add_string (req_tree, &hfi_fcdns_req_nname, tvb,
1117                                    offset+4, 8,
1118                                    tvb_fcwwn_to_str (tvb, offset+4));
1119         }
1120     }
1121 }
1122
1123 static void
1124 dissect_fcdns_rcsid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
1125 {
1126     int offset = 16;            /* past the fc_ct header */
1127
1128     if (req_tree && isreq) {
1129         proto_tree_add_string (req_tree, &hfi_fcdns_req_portid, tvb,
1130                                offset+1, 3,
1131                                tvb_fc_to_str (tvb, offset+1));
1132         dissect_cos_flags(req_tree, tvb, offset+4, &hfi_fcdns_req_cos);
1133     }
1134 }
1135
1136 static void
1137 dissect_fcdns_rptid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
1138 {
1139     int offset = 16;            /* past the fc_ct header */
1140
1141     if (req_tree && isreq) {
1142         proto_tree_add_string (req_tree, &hfi_fcdns_req_portid, tvb,
1143                                offset+1, 3,
1144                                tvb_fc_to_str (tvb, offset+1));
1145         proto_tree_add_item (req_tree, &hfi_fcdns_req_ptype, tvb,
1146                              offset+4, 1, ENC_BIG_ENDIAN);
1147     }
1148 }
1149
1150 static void
1151 dissect_fcdns_rftid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
1152 {
1153     int offset = 16;            /* past the fc_ct header */
1154
1155     if (req_tree && isreq) {
1156         proto_tree_add_string (req_tree, &hfi_fcdns_req_portid, tvb,
1157                                offset+1, 3,
1158                                tvb_fc_to_str (tvb, offset+1));
1159         dissect_fc4type(req_tree, tvb, offset+4, &hfi_fcdns_req_fc4types);
1160     }
1161 }
1162
1163 static void
1164 dissect_fcdns_rspnid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
1165 {
1166     int offset = 16;            /* past the fc_ct header */
1167     guint8 len;
1168
1169     if (req_tree && isreq) {
1170         proto_tree_add_string (req_tree, &hfi_fcdns_req_portid, tvb,
1171                                offset+1, 3,
1172                                tvb_fc_to_str (tvb, offset+1));
1173         proto_tree_add_item (req_tree, &hfi_fcdns_req_spnamelen, tvb,
1174                              offset+4, 1, ENC_BIG_ENDIAN);
1175         len = tvb_get_guint8 (tvb, offset+4);
1176
1177         proto_tree_add_item (req_tree, &hfi_fcdns_req_spname, tvb, offset+5,
1178                              len, ENC_ASCII|ENC_NA);
1179     }
1180 }
1181
1182 static void
1183 dissect_fcdns_rippid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
1184 {
1185     int offset = 16;            /* past the fc_ct header */
1186
1187     if (req_tree && isreq) {
1188         proto_tree_add_string (req_tree, &hfi_fcdns_req_portid, tvb,
1189                                offset+1, 3,
1190                                tvb_fc_to_str (tvb, offset+1));
1191         proto_tree_add_item (req_tree, &hfi_fcdns_req_ip, tvb,
1192                              offset+4, 16, ENC_NA);
1193     }
1194 }
1195
1196 static void
1197 dissect_fcdns_rfdid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
1198 {
1199     int offset = 16;            /* past the fc_ct header */
1200     int len;
1201
1202     if (req_tree && isreq) {
1203         proto_tree_add_string (req_tree, &hfi_fcdns_req_portid, tvb,
1204                                offset+1, 3,
1205                                tvb_fc_to_str (tvb, offset+1));
1206         dissect_fc4type(req_tree, tvb, offset+4, &hfi_fcdns_req_fc4types);
1207
1208         offset += 36;
1209         len = tvb_reported_length_remaining (tvb, offset);
1210
1211         while (len > 0) {
1212             proto_tree_add_item (req_tree, &hfi_fcdns_req_fdesclen, tvb, offset,
1213                                  1, ENC_BIG_ENDIAN);
1214             proto_tree_add_item (req_tree, &hfi_fcdns_req_fdesc, tvb, offset+1,
1215                                  len, ENC_ASCII|ENC_NA);
1216             offset += 256;
1217             len -= 256;
1218         }
1219     }
1220 }
1221
1222 static void
1223 dissect_fcdns_rffid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
1224 {
1225     int offset = 16;            /* past the fc_ct header */
1226
1227     if (req_tree && isreq) {
1228         proto_tree_add_string (req_tree, &hfi_fcdns_req_portid, tvb, offset+1, 3,
1229                                tvb_fc_to_str (tvb, offset+1));
1230         dissect_fc4features_and_type(req_tree, tvb, offset+6);
1231     }
1232 }
1233
1234 static void
1235 dissect_fcdns_ripnn (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
1236 {
1237     int offset = 16;            /* past the fc_ct header */
1238
1239     if (req_tree && isreq) {
1240         proto_tree_add_string (req_tree, &hfi_fcdns_req_nname, tvb, offset, 8,
1241                                tvb_fcwwn_to_str (tvb, offset));
1242         proto_tree_add_item (req_tree, &hfi_fcdns_req_ip, tvb, offset+8, 16, ENC_NA);
1243     }
1244 }
1245
1246 static void
1247 dissect_fcdns_rsnnnn (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
1248 {
1249     int offset = 16;            /* past the fc_ct header */
1250     guint8 len;
1251
1252     if (req_tree && isreq) {
1253         proto_tree_add_string (req_tree, &hfi_fcdns_req_nname, tvb, offset, 8,
1254                                tvb_fcwwn_to_str (tvb, offset));
1255         len = tvb_get_guint8 (tvb, offset+8);
1256
1257         proto_tree_add_item (req_tree, &hfi_fcdns_req_snamelen, tvb, offset+8,
1258                              1, ENC_BIG_ENDIAN);
1259         proto_tree_add_item (req_tree, &hfi_fcdns_req_sname, tvb, offset+9,
1260                              len, ENC_ASCII|ENC_NA);
1261     }
1262 }
1263
1264 static void
1265 dissect_fcdns_daid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
1266 {
1267     int offset = 16;            /* past the fc_ct header */
1268
1269     if (req_tree && isreq) {
1270         proto_tree_add_string (req_tree, &hfi_fcdns_req_portid, tvb, offset+1, 3,
1271                                tvb_fc_to_str (tvb, offset+1));
1272     }
1273 }
1274
1275 static guint8 *
1276 zonenm_to_str (tvbuff_t *tvb, gint offset)
1277 {
1278     int len = tvb_get_guint8 (tvb, offset);
1279     return tvb_get_string_enc(wmem_packet_scope(), tvb, offset+4, len, ENC_ASCII);
1280 }
1281
1282 static void
1283 dissect_fcdns_zone_mbr (tvbuff_t *tvb, proto_tree *zmbr_tree, int offset)
1284 {
1285     guint8 mbrtype;
1286     int idlen;
1287     char dpbuf[2+8+1];
1288     char *str;
1289
1290     mbrtype = tvb_get_guint8 (tvb, offset);
1291     proto_tree_add_uint (zmbr_tree, &hfi_fcdns_zone_mbrtype, tvb,
1292                          offset, 1, mbrtype);
1293     proto_tree_add_text (zmbr_tree, tvb, offset+2, 1, "Flags: 0x%x",
1294                          tvb_get_guint8 (tvb, offset+2));
1295     idlen = tvb_get_guint8 (tvb, offset+3);
1296     proto_tree_add_text (zmbr_tree, tvb, offset+3, 1,
1297                          "Identifier Length: %d", idlen);
1298     switch (mbrtype) {
1299     case FC_SWILS_ZONEMBR_WWN:
1300         proto_tree_add_string (zmbr_tree, &hfi_fcdns_zone_mbrid, tvb,
1301                                offset+4, 8,
1302                                tvb_fcwwn_to_str (tvb, offset+4));
1303         break;
1304     case FC_SWILS_ZONEMBR_DP:
1305         g_snprintf(dpbuf, sizeof(dpbuf), "0x%08x", tvb_get_ntohl (tvb, offset+4));
1306         proto_tree_add_string (zmbr_tree, &hfi_fcdns_zone_mbrid, tvb,
1307                                offset+4, 4, dpbuf);
1308         break;
1309     case FC_SWILS_ZONEMBR_FCID:
1310         proto_tree_add_string (zmbr_tree, &hfi_fcdns_zone_mbrid, tvb,
1311                                offset+4, 4,
1312                                tvb_fc_to_str (tvb, offset+5));
1313         break;
1314     case FC_SWILS_ZONEMBR_ALIAS:
1315         str = zonenm_to_str (tvb, offset+4);
1316         proto_tree_add_string (zmbr_tree, &hfi_fcdns_zone_mbrid, tvb,
1317                                offset+4, idlen, str);
1318         break;
1319     default:
1320         proto_tree_add_string (zmbr_tree, &hfi_fcdns_zone_mbrid, tvb,
1321                                offset+4, idlen,
1322                                "Unknown member type format");
1323
1324     }
1325 }
1326
1327 static void
1328 dissect_fcdns_swils_entries (tvbuff_t *tvb, proto_tree *tree, int offset)
1329 {
1330     int numrec, i, len;
1331     guint8 objfmt;
1332
1333     numrec = tvb_get_ntohl (tvb, offset);
1334
1335     if (tree) {
1336         proto_tree_add_text (tree, tvb, offset, 4, "Number of Entries: %d",
1337                              numrec);
1338         offset += 4;
1339
1340         for (i = 0; i < numrec; i++) {
1341             objfmt = tvb_get_guint8 (tvb, offset);
1342
1343             proto_tree_add_item (tree, &hfi_fcdns_sw2_objfmt, tvb, offset, 1, ENC_BIG_ENDIAN);
1344             proto_tree_add_string (tree, &hfi_fcdns_rply_ownerid, tvb, offset+1,
1345                                    3, fc_to_str (tvb_get_string_enc(wmem_packet_scope(), tvb, offset+1,
1346                                                               3, ENC_ASCII)));
1347             proto_tree_add_item (tree, &hfi_fcdns_rply_ptype, tvb, offset+4,
1348                                  1, ENC_BIG_ENDIAN);
1349             proto_tree_add_string (tree, &hfi_fcdns_rply_portid, tvb, offset+5, 3,
1350                                    tvb_fc_to_str (tvb, offset+5));
1351             proto_tree_add_string (tree, &hfi_fcdns_rply_pname, tvb, offset+8, 8,
1352                                    tvb_fcwwn_to_str (tvb, offset+8));
1353             offset += 16;
1354             if (!(objfmt & 0x1)) {
1355                 len = tvb_get_guint8 (tvb, offset);
1356                 proto_tree_add_item (tree, &hfi_fcdns_rply_spnamelen, tvb,
1357                                      offset, 1, ENC_BIG_ENDIAN);
1358                 proto_tree_add_item (tree, &hfi_fcdns_rply_spname, tvb,
1359                                      offset+1, len, ENC_ASCII|ENC_NA);
1360                 offset += 256;
1361             }
1362             proto_tree_add_string (tree, &hfi_fcdns_rply_nname, tvb, offset, 8,
1363                                    tvb_fcwwn_to_str (tvb, offset));
1364             offset += 8;
1365             if (!(objfmt & 0x1)) {
1366                 len = tvb_get_guint8 (tvb, offset);
1367                 proto_tree_add_item (tree, &hfi_fcdns_rply_snamelen, tvb,
1368                                      offset, 1, ENC_BIG_ENDIAN);
1369                 proto_tree_add_item (tree, &hfi_fcdns_rply_sname, tvb,
1370                                      offset+1, len, ENC_ASCII|ENC_NA);
1371                 offset += 256;
1372             }
1373             proto_tree_add_item (tree, &hfi_fcdns_rply_ipa, tvb, offset, 8, ENC_NA);
1374             proto_tree_add_item (tree, &hfi_fcdns_rply_ipnode, tvb, offset+8, 16,
1375                                  ENC_NA);
1376             dissect_cos_flags(tree, tvb, offset+24, &hfi_fcdns_reply_cos);
1377             dissect_fc4type(tree, tvb, offset+28, &hfi_fcdns_rply_gft);
1378             proto_tree_add_item (tree, &hfi_fcdns_rply_ipport, tvb, offset+60,
1379                                  16, ENC_NA);
1380             proto_tree_add_string (tree, &hfi_fcdns_rply_fpname, tvb, offset+76,
1381                                    8, tvb_fcwwn_to_str (tvb, offset+76));
1382             proto_tree_add_string (tree, &hfi_fcdns_rply_hrdaddr, tvb, offset+85,
1383                                    3, tvb_fc_to_str (tvb, offset+85));
1384             offset += 88;
1385             if (objfmt & 0x2) {
1386                 dissect_fc4features(tree, tvb, offset);
1387                 if (tvb_get_guint8 (tvb, offset+129)) {
1388                     proto_tree_add_item (tree, &hfi_fcdns_rply_fc4type, tvb,
1389                                          offset+128, 1, ENC_BIG_ENDIAN);
1390                     proto_tree_add_item (tree, &hfi_fcdns_num_fc4desc, tvb,
1391                                          offset+129, 1, ENC_BIG_ENDIAN);
1392                     len = tvb_get_guint8 (tvb, offset+132);
1393                     proto_tree_add_item (tree, &hfi_fcdns_rply_fc4desclen, tvb,
1394                                          offset+132, 1, ENC_BIG_ENDIAN);
1395                     proto_tree_add_item (tree, &hfi_fcdns_rply_fc4desc, tvb,
1396                                          offset+133, len, ENC_NA);
1397                 }
1398                 else {
1399                     proto_tree_add_item (tree, &hfi_fcdns_num_fc4desc, tvb,
1400                                          offset+129, 1, ENC_BIG_ENDIAN);
1401                 }
1402                 offset += 388;  /* FC4 desc is 260 bytes, maybe padded */
1403             }
1404         }
1405     }
1406 }
1407
1408 static void
1409 dissect_fcdns_geid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
1410 {
1411     int offset = 16;            /* past the fc_ct header */
1412
1413     if (isreq) {
1414         if (req_tree) {
1415             proto_tree_add_string (req_tree, &hfi_fcdns_req_portid, tvb, offset+1,
1416                                    3, tvb_fc_to_str (tvb, offset+1));
1417         }
1418     }
1419     else {
1420         dissect_fcdns_swils_entries (tvb, req_tree, offset);
1421     }
1422 }
1423
1424 static void
1425 dissect_fcdns_gepn (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
1426 {
1427     int offset = 16;            /* past the fc_ct header */
1428     if (isreq) {
1429         if (req_tree) {
1430             proto_tree_add_string (req_tree, &hfi_fcdns_req_pname, tvb, offset, 8,
1431                                    tvb_fcwwn_to_str (tvb, offset));
1432         }
1433     }
1434     else {
1435         dissect_fcdns_swils_entries (tvb, req_tree, offset);
1436     }
1437 }
1438
1439 static void
1440 dissect_fcdns_genn (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
1441 {
1442     int offset = 16;            /* past the fc_ct header */
1443
1444     if (isreq) {
1445         if (req_tree) {
1446             proto_tree_add_string (req_tree, &hfi_fcdns_req_nname, tvb, offset, 8,
1447                                    tvb_fcwwn_to_str (tvb, offset));
1448         }
1449     }
1450     else {
1451         dissect_fcdns_swils_entries (tvb, req_tree, offset);
1452     }
1453 }
1454
1455 static void
1456 dissect_fcdns_geip (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
1457 {
1458     int offset = 16;            /* past the fc_ct header */
1459
1460     if (isreq) {
1461         if (req_tree) {
1462             proto_tree_add_item (req_tree, &hfi_fcdns_req_ip, tvb, offset, 16, ENC_NA);
1463         }
1464     }
1465     else {
1466         dissect_fcdns_swils_entries (tvb, req_tree, offset);
1467     }
1468 }
1469
1470 static void
1471 dissect_fcdns_geft (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
1472 {
1473     int offset = 16;            /* past the fc_ct header */
1474
1475     if (isreq) {
1476         if (req_tree) {
1477             dissect_fc4type(req_tree, tvb, offset, &hfi_fcdns_fc4type);
1478         }
1479     }
1480     else {
1481         dissect_fcdns_swils_entries (tvb, req_tree, offset);
1482     }
1483 }
1484
1485 static void
1486 dissect_fcdns_gept (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
1487 {
1488     int offset = 16;            /* past the fc_ct header */
1489
1490     if (isreq) {
1491         if (req_tree) {
1492             proto_tree_add_item (req_tree, &hfi_fcdns_req_ptype, tvb, offset+3,
1493                                  1, ENC_BIG_ENDIAN);
1494         }
1495     }
1496     else {
1497         dissect_fcdns_swils_entries (tvb, req_tree, offset);
1498     }
1499 }
1500
1501 static void
1502 dissect_fcdns_gezm (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
1503 {
1504     int offset = 16;            /* past the fc_ct header */
1505
1506     if (isreq) {
1507         if (req_tree) {
1508             dissect_fcdns_zone_mbr (tvb, req_tree, offset);
1509         }
1510     }
1511     else {
1512         dissect_fcdns_swils_entries (tvb, req_tree, offset);
1513     }
1514 }
1515
1516 static void
1517 dissect_fcdns_gezn (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
1518 {
1519     int offset = 16;            /* past the fc_ct header */
1520     int str_len;
1521
1522     if (isreq) {
1523         if (req_tree) {
1524             str_len = tvb_get_guint8 (tvb, offset);
1525             proto_tree_add_text (req_tree, tvb, offset, 1, "Name Length: %d",
1526                                  str_len);
1527             proto_tree_add_item (req_tree, &hfi_fcdns_zonenm, tvb, offset+3,
1528                                  str_len, ENC_ASCII|ENC_NA);
1529         }
1530     }
1531     else {
1532         dissect_fcdns_swils_entries (tvb, req_tree, offset);
1533     }
1534 }
1535
1536 static void
1537 dissect_fcdns_geipp (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
1538 {
1539     int offset = 16;            /* past the fc_ct header */
1540
1541     if (isreq) {
1542         if (req_tree) {
1543             proto_tree_add_item (req_tree, &hfi_fcdns_portip, tvb, offset, 4, ENC_BIG_ENDIAN);
1544         }
1545     }
1546     else {
1547         dissect_fcdns_swils_entries (tvb, req_tree, offset);
1548     }
1549 }
1550
1551 static void
1552 dissect_fcdns_geff (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
1553 {
1554     int offset = 16;            /* past the fc_ct header */
1555
1556     if (isreq) {
1557         if (req_tree) {
1558             dissect_fc4features(req_tree, tvb, offset);
1559         }
1560     }
1561     else {
1562         dissect_fcdns_swils_entries (tvb, req_tree, offset);
1563     }
1564 }
1565
1566 static void
1567 dissect_fcdns_rjt (tvbuff_t *tvb, proto_tree *req_tree)
1568 {
1569     int offset = 0;
1570
1571     if (req_tree) {
1572         proto_tree_add_item (req_tree, &hfi_fcdns_reason, tvb, offset+13, 1, ENC_BIG_ENDIAN);
1573         proto_tree_add_item (req_tree, &hfi_fcdns_rjtdetail, tvb, offset+14, 1,
1574                              ENC_BIG_ENDIAN);
1575         proto_tree_add_item (req_tree, &hfi_fcdns_vendor, tvb, offset+15, 1, ENC_BIG_ENDIAN);
1576     }
1577 }
1578
1579 static int
1580 dissect_fcdns (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1581 {
1582     /* Set up structures needed to add the protocol subtree and manage it */
1583     proto_item *ti = NULL;
1584     proto_tree *fcdns_tree = NULL;
1585     int offset = 0;
1586     int opcode,
1587         failed_opcode = 0;
1588     int isreq = 1;
1589     fc_ct_preamble cthdr;
1590     conversation_t *conversation;
1591     fcdns_conv_data_t *cdata;
1592     fcdns_conv_key_t ckey, *req_key;
1593     fc_hdr *fchdr;
1594
1595     /* Reject the packet if data is NULL */
1596     if (data == NULL)
1597         return 0;
1598     fchdr = (fc_hdr *)data;
1599
1600     tvb_memcpy (tvb, (guint8 *)&cthdr, offset, FCCT_PRMBL_SIZE);
1601     cthdr.revision = tvb_get_guint8 (tvb, offset);
1602     cthdr.in_id = tvb_get_ntoh24 (tvb, offset+1);
1603     cthdr.opcode = g_ntohs (cthdr.opcode);
1604     opcode = cthdr.opcode;
1605     cthdr.maxres_size = g_ntohs (cthdr.maxres_size);
1606
1607     /* Determine the type of server the request/response is for */
1608     if (cthdr.gstype == FCCT_GSTYPE_DIRSVC)
1609         col_set_str (pinfo->cinfo, COL_PROTOCOL, "dNS");
1610     else
1611         col_set_str (pinfo->cinfo, COL_PROTOCOL, "Unzoned NS");
1612
1613     if (tree) {
1614         if (cthdr.gstype == FCCT_GSTYPE_DIRSVC) {
1615             ti = proto_tree_add_protocol_format (tree, hfi_fcdns->id, tvb, 0,
1616                                                  -1,
1617                                                  "dNS");
1618             fcdns_tree = proto_item_add_subtree (ti, ett_fcdns);
1619         }
1620         else {
1621             ti = proto_tree_add_protocol_format (tree, hfi_fcdns->id, tvb, 0,
1622                                                  -1,
1623                                                  "Unzoned NS");
1624             fcdns_tree = proto_item_add_subtree (ti, ett_fcdns);
1625         }
1626     }
1627
1628     if ((opcode != FCCT_MSG_ACC) && (opcode != FCCT_MSG_RJT)) {
1629         conversation = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst,
1630                                           pinfo->ptype, fchdr->oxid,
1631                                           fchdr->rxid, NO_PORT2);
1632         if (!conversation) {
1633             conversation = conversation_new (pinfo->fd->num, &pinfo->src, &pinfo->dst,
1634                                              pinfo->ptype, fchdr->oxid,
1635                                              fchdr->rxid, NO_PORT2);
1636         }
1637
1638         ckey.conv_idx = conversation->index;
1639
1640         cdata = (fcdns_conv_data_t *)g_hash_table_lookup (fcdns_req_hash,
1641                                                             &ckey);
1642         if (cdata) {
1643             /* Since we never free the memory used by an exchange, this maybe a
1644              * case of another request using the same exchange as a previous
1645              * req.
1646              */
1647             cdata->opcode = opcode;
1648         }
1649         else {
1650             req_key = wmem_new(wmem_file_scope(), fcdns_conv_key_t);
1651             req_key->conv_idx = conversation->index;
1652
1653             cdata = wmem_new(wmem_file_scope(), fcdns_conv_data_t);
1654             cdata->opcode = opcode;
1655
1656             g_hash_table_insert (fcdns_req_hash, req_key, cdata);
1657         }
1658         col_add_str (pinfo->cinfo, COL_INFO, val_to_str (opcode, fc_dns_opcode_val,
1659                                                           "0x%x"));
1660     }
1661     else {
1662         /* Opcode is ACC or RJT */
1663         conversation = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst,
1664                                           pinfo->ptype, fchdr->oxid,
1665                                           fchdr->rxid, NO_PORT2);
1666         isreq = 0;
1667         if (!conversation) {
1668             if (opcode == FCCT_MSG_ACC) {
1669                 col_add_str (pinfo->cinfo, COL_INFO,
1670                                  val_to_str (opcode, fc_dns_opcode_val,
1671                                              "0x%x"));
1672                 /* No record of what this accept is for. Can't decode */
1673                 proto_tree_add_text (fcdns_tree, tvb, 0, -1,
1674                                      "No record of Exchg. Unable to decode MSG_ACC/RJT");
1675                 return 0;
1676             }
1677         }
1678         else {
1679             ckey.conv_idx = conversation->index;
1680
1681             cdata = (fcdns_conv_data_t *)g_hash_table_lookup (fcdns_req_hash, &ckey);
1682
1683             if (cdata != NULL) {
1684                 if (opcode == FCCT_MSG_ACC) {
1685                     opcode = cdata->opcode;
1686                 }
1687                 else
1688                     failed_opcode = cdata->opcode;
1689             }
1690
1691             if (opcode != FCCT_MSG_RJT) {
1692                 col_add_fstr (pinfo->cinfo, COL_INFO, "ACC (%s)",
1693                                 val_to_str (opcode, fc_dns_opcode_val,
1694                                             "0x%x"));
1695             }
1696             else {
1697                 col_add_fstr (pinfo->cinfo, COL_INFO, "RJT (%s)",
1698                                 val_to_str (failed_opcode,
1699                                             fc_dns_opcode_val,
1700                                             "0x%x"));
1701             }
1702
1703             if (tree) {
1704                 if ((cdata == NULL) && (opcode != FCCT_MSG_RJT)) {
1705                     /* No record of what this accept is for. Can't decode */
1706                     proto_tree_add_text (fcdns_tree, tvb, 0, -1,
1707                                          "No record of Exchg. Unable to decode MSG_ACC/RJT");
1708                     return 0;
1709                 }
1710             }
1711         }
1712     }
1713
1714      if (tree) {
1715         proto_tree_add_item (fcdns_tree, &hfi_fcdns_opcode, tvb, offset+8, 2, ENC_BIG_ENDIAN);
1716         proto_tree_add_item (fcdns_tree, &hfi_fcdns_maxres_size, tvb, offset+10,
1717                              2, ENC_BIG_ENDIAN);
1718     }
1719
1720     switch (opcode) {
1721     case FCCT_MSG_RJT:
1722         dissect_fcdns_rjt (tvb, fcdns_tree);
1723         break;
1724     case FCDNS_GA_NXT:
1725         dissect_fcdns_ganxt (tvb, fcdns_tree, isreq);
1726         break;
1727     case FCDNS_GPN_ID:
1728         dissect_fcdns_gpnid (tvb, fcdns_tree, isreq);
1729         break;
1730     case FCDNS_GNN_ID:
1731         dissect_fcdns_gnnid (tvb, fcdns_tree, isreq);
1732         break;
1733     case FCDNS_GCS_ID:
1734         dissect_fcdns_gcsid (tvb, fcdns_tree, isreq);
1735         break;
1736     case FCDNS_GFT_ID:
1737         dissect_fcdns_gftid (tvb, fcdns_tree, isreq);
1738         break;
1739     case FCDNS_GSPN_ID:
1740         dissect_fcdns_gspnid (tvb, fcdns_tree, isreq);
1741         break;
1742     case FCDNS_GPT_ID:
1743         dissect_fcdns_gptid (tvb, fcdns_tree, isreq);
1744         break;
1745     case FCDNS_GFPN_ID:
1746         dissect_fcdns_gfpnid (tvb, fcdns_tree, isreq);
1747         break;
1748     case FCDNS_GFD_ID:
1749         dissect_fcdns_gfdid (tvb, fcdns_tree, isreq);
1750         break;
1751     case FCDNS_GFF_ID:
1752         dissect_fcdns_gffid (tvb, fcdns_tree, isreq);
1753         break;
1754     case FCDNS_GID_PN:
1755         dissect_fcdns_gidpn (tvb, fcdns_tree, isreq);
1756         break;
1757     case FCDNS_GIPP_PN:
1758         dissect_fcdns_gipppn (tvb, fcdns_tree, isreq);
1759         break;
1760     case FCDNS_GID_NN:
1761         dissect_fcdns_gidnn (tvb, fcdns_tree, isreq);
1762         break;
1763     case FCDNS_GPN_NN:
1764         dissect_fcdns_gpnnn (tvb, fcdns_tree, isreq);
1765         break;
1766     case FCDNS_GIP_NN:
1767         dissect_fcdns_gipnn (tvb, fcdns_tree, isreq);
1768         break;
1769     case FCDNS_GSNN_NN:
1770         dissect_fcdns_gsnnnn (tvb, fcdns_tree, isreq);
1771         break;
1772     case FCDNS_GID_FT:
1773         dissect_fcdns_gidft (tvb, fcdns_tree, isreq);
1774         break;
1775     case FCDNS_GPN_FT:
1776         dissect_fcdns_gpnft (tvb, fcdns_tree, isreq);
1777         break;
1778     case FCDNS_GNN_FT:
1779         dissect_fcdns_gnnft (tvb, fcdns_tree, isreq);
1780         break;
1781     case FCDNS_GID_PT:
1782         dissect_fcdns_gidpt (tvb, fcdns_tree, isreq);
1783         break;
1784     case FCDNS_GID_IPP:
1785         dissect_fcdns_gidipp (tvb, fcdns_tree, isreq);
1786         break;
1787     case FCDNS_GID_FF:
1788         dissect_fcdns_gidff (tvb, fcdns_tree, isreq);
1789         break;
1790     case FCDNS_RPN_ID:
1791         dissect_fcdns_rpnid (tvb, fcdns_tree, isreq);
1792         break;
1793     case FCDNS_RNN_ID:
1794         dissect_fcdns_rnnid (tvb, fcdns_tree, isreq);
1795         break;
1796     case FCDNS_RCS_ID:
1797         dissect_fcdns_rcsid (tvb, fcdns_tree, isreq);
1798         break;
1799     case FCDNS_RPT_ID:
1800         dissect_fcdns_rptid (tvb, fcdns_tree, isreq);
1801         break;
1802     case FCDNS_RFT_ID:
1803         dissect_fcdns_rftid (tvb, fcdns_tree, isreq);
1804         break;
1805     case FCDNS_RSPN_ID:
1806         dissect_fcdns_rspnid (tvb, fcdns_tree, isreq);
1807         break;
1808     case FCDNS_RIPP_ID:
1809         dissect_fcdns_rippid (tvb, fcdns_tree, isreq);
1810         break;
1811     case FCDNS_RFD_ID:
1812         dissect_fcdns_rfdid (tvb, fcdns_tree, isreq);
1813         break;
1814     case FCDNS_RFF_ID:
1815         dissect_fcdns_rffid (tvb, fcdns_tree, isreq);
1816         break;
1817     case FCDNS_RIP_NN:
1818         dissect_fcdns_ripnn (tvb, fcdns_tree, isreq);
1819         break;
1820     case FCDNS_RSNN_NN:
1821         dissect_fcdns_rsnnnn (tvb, fcdns_tree, isreq);
1822         break;
1823     case FCDNS_DA_ID:
1824         dissect_fcdns_daid (tvb, fcdns_tree, isreq);
1825         break;
1826     case FCDNS_GE_ID:
1827         dissect_fcdns_geid (tvb, fcdns_tree, isreq);
1828         break;
1829     case FCDNS_GE_PN:
1830         dissect_fcdns_gepn (tvb, fcdns_tree, isreq);
1831         break;
1832     case FCDNS_GE_NN:
1833         dissect_fcdns_genn (tvb, fcdns_tree, isreq);
1834         break;
1835     case FCDNS_GE_IP:
1836         dissect_fcdns_geip (tvb, fcdns_tree, isreq);
1837         break;
1838     case FCDNS_GE_FT:
1839         dissect_fcdns_geft (tvb, fcdns_tree, isreq);
1840         break;
1841     case FCDNS_GE_PT:
1842         dissect_fcdns_gept (tvb, fcdns_tree, isreq);
1843         break;
1844     case FCDNS_GE_ZM:
1845         dissect_fcdns_gezm (tvb, fcdns_tree, isreq);
1846         break;
1847     case FCDNS_GE_ZN:
1848         dissect_fcdns_gezn (tvb, fcdns_tree, isreq);
1849         break;
1850     case FCDNS_GE_IPP:
1851         dissect_fcdns_geipp (tvb, fcdns_tree, isreq);
1852         break;
1853     case FCDNS_GE_FF:
1854         dissect_fcdns_geff (tvb, fcdns_tree, isreq);
1855         break;
1856     default:
1857         break;
1858     }
1859
1860     return tvb_length(tvb);
1861 }
1862
1863 /* Register the protocol with Wireshark */
1864
1865 void
1866 proto_register_fcdns (void)
1867 {
1868 #ifndef HAVE_HFI_SECTION_INIT
1869     static header_field_info *hfi[] = {
1870         /* &hfi_fcdns_gssubtype */
1871         &hfi_fcdns_opcode,
1872         &hfi_fcdns_req_portid,
1873         &hfi_fcdns_rply_pname,
1874         &hfi_fcdns_rply_nname,
1875         &hfi_fcdns_rply_snamelen,
1876         &hfi_fcdns_rply_sname,
1877         &hfi_fcdns_rply_ptype,
1878         &hfi_fcdns_rply_fpname,
1879         &hfi_fcdns_req_pname,
1880         &hfi_fcdns_rply_portid,
1881         &hfi_fcdns_req_nname,
1882         &hfi_fcdns_req_domainscope,
1883         &hfi_fcdns_req_areascope,
1884         &hfi_fcdns_req_fc4type,
1885         &hfi_fcdns_req_ptype,
1886         &hfi_fcdns_req_ip,
1887         &hfi_fcdns_rply_fc4type,
1888         &hfi_fcdns_req_snamelen,
1889         &hfi_fcdns_req_sname,
1890         &hfi_fcdns_rply_spnamelen,
1891         &hfi_fcdns_rply_spname,
1892         &hfi_fcdns_rply_ipa,
1893         &hfi_fcdns_rply_ipnode,
1894         &hfi_fcdns_rply_ipport,
1895         &hfi_fcdns_rply_fc4desclen,
1896         &hfi_fcdns_rply_fc4desc,
1897         &hfi_fcdns_rply_hrdaddr,
1898         &hfi_fcdns_req_fdesclen,
1899         &hfi_fcdns_req_fdesc,
1900         &hfi_fcdns_req_spnamelen,
1901         &hfi_fcdns_req_spname,
1902         &hfi_fcdns_reason,
1903         &hfi_fcdns_rjtdetail,
1904         &hfi_fcdns_vendor,
1905         &hfi_fcdns_zone_mbrtype,
1906         &hfi_fcdns_zone_mbrid,
1907         &hfi_fcdns_zonenm,
1908         &hfi_fcdns_portip,
1909         &hfi_fcdns_sw2_objfmt,
1910         &hfi_fcdns_num_fc4desc,
1911         &hfi_fcdns_rply_ownerid,
1912         &hfi_fcdns_maxres_size,
1913         &hfi_fcdns_reply_cos,
1914         &hfi_fcdns_req_cos,
1915         &hfi_fcdns_cos_f,
1916         &hfi_fcdns_cos_1,
1917         &hfi_fcdns_cos_2,
1918         &hfi_fcdns_cos_3,
1919         &hfi_fcdns_cos_4,
1920         &hfi_fcdns_cos_6,
1921         &hfi_fcdns_fc4type_llcsnap,
1922         &hfi_fcdns_fc4type_ip,
1923         &hfi_fcdns_fc4type_fcp,
1924         &hfi_fcdns_fc4type_swils,
1925         &hfi_fcdns_fc4type_snmp,
1926         &hfi_fcdns_fc4type_gs3,
1927         &hfi_fcdns_fc4type_vi,
1928         &hfi_fcdns_rply_gft,
1929         &hfi_fcdns_req_fc4types,
1930         &hfi_fcdns_fc4type,
1931         &hfi_fcdns_fc4features,
1932         &hfi_fcdns_fc4features_i,
1933         &hfi_fcdns_fc4features_t,
1934     };
1935 #endif
1936
1937     static gint *ett[] = {
1938         &ett_fcdns,
1939         &ett_cos_flags,
1940         &ett_fc4flags,
1941         &ett_fc4features,
1942     };
1943
1944     int proto_fcdns;
1945
1946     proto_fcdns = proto_register_protocol("Fibre Channel Name Server",
1947                                           "FC-dNS", "fcdns");
1948     hfi_fcdns = proto_registrar_get_nth(proto_fcdns);
1949
1950     proto_register_fields(proto_fcdns, hfi, array_length(hfi));
1951     proto_register_subtree_array(ett, array_length(ett));
1952     register_init_routine (&fcdns_init_protocol);
1953
1954     dns_handle = new_create_dissector_handle (dissect_fcdns, proto_fcdns);
1955 }
1956
1957 void
1958 proto_reg_handoff_fcdns (void)
1959 {
1960     dissector_add_uint("fcct.server", FCCT_GSRVR_DNS, dns_handle);
1961     dissector_add_uint("fcct.server", FCCT_GSRVR_UNS, dns_handle);
1962 }