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