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