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