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