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