MSWSP: fix dissect_mswsp_smb()
[wireshark-wip.git] / epan / dissectors / packet-fcfcs.c
blob264018f2b6480f6f6ed39b2b46f0aec1f0cfd60a
1 /* packet-fcfcs.c
2 * Routines for FC Fabric Configuration Server
3 * Copyright 2001, Dinesh G Dutt <ddutt@andiamo.com>
5 * $Id$
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
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.
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.
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.
26 #include "config.h"
28 #include <glib.h>
30 #include <epan/packet.h>
31 #include <epan/to_str.h>
32 #include <epan/wmem/wmem.h>
33 #include <epan/conversation.h>
34 #include <epan/etypes.h>
35 #include "packet-scsi.h"
36 #include "packet-fc.h"
37 #include "packet-fcct.h"
38 #include "packet-fcfcs.h"
41 * See the FC-GS3 specification.
44 /* Initialize the protocol and registered fields */
45 static int proto_fcfcs = -1;
46 static int hf_fcs_opcode = -1;
47 static int hf_fcs_iename = -1;
48 static int hf_fcs_ietype = -1;
49 static int hf_fcs_iedomainid = -1;
50 static int hf_fcs_mgmtid = -1;
51 static int hf_fcs_fabricname = -1;
52 static int hf_fcs_mgmtaddr = -1;
53 static int hf_fcs_lname = -1;
54 static int hf_fcs_vendorname = -1;
55 static int hf_fcs_modelname = -1;
56 static int hf_fcs_portname = -1;
57 static int hf_fcs_portmodtype = -1;
58 static int hf_fcs_porttxtype = -1;
59 static int hf_fcs_porttype = -1;
60 static int hf_fcs_physportnum = -1;
61 static int hf_fcs_portflags = -1;
62 static int hf_fcs_portstate = -1;
63 static int hf_fcs_platformname = -1;
64 static int hf_fcs_platformnname = -1;
65 static int hf_fcs_platformtype = -1;
66 static int hf_fcs_platformaddr = -1;
67 static int hf_fcs_reason = -1;
68 static int hf_fcs_rjtdetail = -1;
69 static int hf_fcs_vendor = -1;
70 static int hf_fcs_numcap = -1;
71 static int hf_fcs_mgmt_subtype = -1;
72 static int hf_fcs_unsmask = -1;
73 static int hf_fcs_vnd_capmask = -1;
74 static int hf_fcs_fcsmask = -1;
75 static int hf_fcs_maxres_size = -1;
76 static int hf_fcs_releasecode = -1;
79 /* Initialize the subtree pointers */
80 static gint ett_fcfcs = -1;
82 typedef struct _fcfcs_conv_key {
83 guint32 conv_idx;
84 } fcfcs_conv_key_t;
86 typedef struct _fcfcs_conv_data {
87 guint32 opcode;
88 } fcfcs_conv_data_t;
90 static GHashTable *fcfcs_req_hash = NULL;
92 static dissector_handle_t data_handle;
95 * Hash Functions
97 static gint
98 fcfcs_equal(gconstpointer v, gconstpointer w)
100 const fcfcs_conv_key_t *v1 = (const fcfcs_conv_key_t *)v;
101 const fcfcs_conv_key_t *v2 = (const fcfcs_conv_key_t *)w;
103 return (v1->conv_idx == v2->conv_idx);
106 static guint
107 fcfcs_hash (gconstpointer v)
109 const fcfcs_conv_key_t *key = (const fcfcs_conv_key_t *)v;
110 guint val;
112 val = key->conv_idx;
114 return val;
118 * Protocol initialization
120 static void
121 fcfcs_init_protocol(void)
123 if (fcfcs_req_hash)
124 g_hash_table_destroy (fcfcs_req_hash);
126 fcfcs_req_hash = g_hash_table_new(fcfcs_hash, fcfcs_equal);
129 /* Code to actually dissect the packets */
130 static void
131 dissect_fcfcs_giel (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
133 int offset = 16; /* past the ct header */
134 int numelem, i;
136 if (!isreq && tree) {
137 numelem = tvb_get_ntohl (tvb, offset);
139 proto_tree_add_text (tree, tvb, offset, 4, "Number of IE entries: 0x%d",
140 numelem);
141 offset += 4;
142 for (i = 0; i < numelem; i++) {
143 proto_tree_add_string (tree, hf_fcs_iename, tvb, offset, 8,
144 tvb_fcwwn_to_str (tvb, offset));
145 proto_tree_add_item (tree, hf_fcs_ietype, tvb, offset+11, 1, ENC_BIG_ENDIAN);
146 offset += 12;
151 static void
152 dissect_fcfcs_giet (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
154 int offset = 16; /* past the fcct header */
156 if (tree) {
157 if (isreq) {
158 proto_tree_add_string (tree, hf_fcs_iename, tvb, offset, 8,
159 tvb_fcwwn_to_str (tvb, offset));
161 else {
162 proto_tree_add_item (tree, hf_fcs_ietype, tvb, offset+3, 1, ENC_BIG_ENDIAN);
167 static void
168 dissect_fcfcs_gdid (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
170 int offset = 16; /* past the fcct header */
172 if (tree) {
173 if (isreq) {
174 proto_tree_add_string (tree, hf_fcs_iename, tvb, offset, 8,
175 tvb_fcwwn_to_str (tvb, offset));
177 else {
178 proto_tree_add_item (tree, hf_fcs_iedomainid, tvb, offset+1, 1, ENC_BIG_ENDIAN);
183 static void
184 dissect_fcfcs_gmid (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
186 int offset = 16; /* past the fcct header */
188 if (tree) {
189 if (isreq) {
190 proto_tree_add_string (tree, hf_fcs_iename, tvb, offset, 8,
191 tvb_fcwwn_to_str (tvb, offset));
193 else {
194 proto_tree_add_string (tree, hf_fcs_mgmtid, tvb, offset+1, 3,
195 tvb_fc_to_str (tvb, offset+1));
200 static void
201 dissect_fcfcs_gfn (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
203 int offset = 16; /* past the fcct header */
205 if (tree) {
206 if (isreq) {
207 proto_tree_add_string (tree, hf_fcs_iename, tvb, offset, 8,
208 tvb_fcwwn_to_str (tvb, offset));
210 else {
211 proto_tree_add_string (tree, hf_fcs_fabricname, tvb, offset, 8,
212 tvb_fcwwn_to_str (tvb, offset));
217 static void
218 dissect_fcfcs_gieln (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
220 int offset = 16; /* past the fcct header */
222 if (tree) {
223 if (isreq) {
224 proto_tree_add_string (tree, hf_fcs_iename, tvb, offset, 8,
225 tvb_fcwwn_to_str (tvb, offset));
227 else {
228 proto_tree_add_text (tree, tvb, offset, 1, "Name Length: %d",
229 tvb_get_guint8 (tvb, offset));
230 proto_tree_add_item (tree, hf_fcs_lname, tvb, offset+1,
231 tvb_get_guint8 (tvb, offset), ENC_ASCII|ENC_NA);
236 static void
237 dissect_fcfcs_gmal (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
239 int offset = 16; /* past the fcct header */
240 int numelem, i;
242 if (tree) {
243 if (isreq) {
244 proto_tree_add_string (tree, hf_fcs_iename, tvb, offset, 8,
245 tvb_fcwwn_to_str (tvb, offset));
247 else {
248 numelem = tvb_get_ntohl (tvb, offset);
249 proto_tree_add_text (tree, tvb, offset, 4,
250 "Number of Mgmt. Addresses: 0x%d", numelem);
252 offset += 4;
253 for (i = 0; i < numelem; i++) {
254 proto_tree_add_text (tree, tvb, offset, 1, "Name Length: %d",
255 tvb_get_guint8 (tvb, offset));
256 proto_tree_add_item (tree, hf_fcs_mgmtaddr, tvb, offset+1,
257 tvb_get_guint8 (tvb, offset), ENC_ASCII|ENC_NA);
258 offset += 256;
264 static void
265 dissect_fcfcs_gieil (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
267 int offset = 16; /* past the fcct header */
268 int len, tot_len, prevlen;
270 if (tree) {
271 if (isreq) {
272 proto_tree_add_string (tree, hf_fcs_iename, tvb, offset, 8,
273 tvb_fcwwn_to_str (tvb, offset));
275 else {
276 tot_len = tvb_get_guint8 (tvb, offset+3);
277 proto_tree_add_text (tree, tvb, offset+3, 1, "List Length: %d",
278 tot_len);
280 prevlen = 0;
281 len = tvb_strsize(tvb, offset+4);
282 proto_tree_add_item (tree, hf_fcs_vendorname, tvb, offset+4,
283 len, ENC_ASCII|ENC_NA);
284 prevlen += len;
286 len = tvb_strsize(tvb, offset+4+prevlen);
287 proto_tree_add_item (tree, hf_fcs_modelname, tvb, offset+4+prevlen,
288 len, ENC_ASCII|ENC_NA);
289 prevlen += len;
291 len = tvb_strsize(tvb, offset+4+prevlen);
292 proto_tree_add_item (tree, hf_fcs_releasecode, tvb,
293 offset+4+prevlen, len, ENC_ASCII|ENC_NA);
294 prevlen += len;
295 offset += (4+prevlen);
296 while (tot_len > prevlen) {
297 len = tvb_strsize(tvb, offset);
298 proto_tree_add_text (tree, tvb, offset, len,
299 "Vendor-specific Information: %s",
300 tvb_format_text(tvb, offset, len-1));
301 prevlen += len;
302 offset += len;
308 static void
309 dissect_fcfcs_gpl (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
311 int offset = 16; /* past the fcct header */
312 int numelem, i;
314 if (tree) {
315 if (isreq) {
316 proto_tree_add_string (tree, hf_fcs_iename, tvb, offset, 8,
317 tvb_fcwwn_to_str (tvb, offset));
319 else {
320 numelem = tvb_get_ntohl (tvb, offset);
321 proto_tree_add_text (tree, tvb, offset, 4,
322 "Number of Port Entries: %d",
323 numelem);
324 offset += 4;
326 for (i = 0; i < numelem; i++) {
327 proto_tree_add_string (tree, hf_fcs_portname, tvb, offset, 8,
328 tvb_fcwwn_to_str (tvb, offset));
329 proto_tree_add_item (tree, hf_fcs_portmodtype, tvb, offset+9,
330 1, ENC_BIG_ENDIAN);
331 proto_tree_add_item (tree, hf_fcs_porttxtype, tvb, offset+10,
332 1, ENC_BIG_ENDIAN);
333 proto_tree_add_item (tree, hf_fcs_porttype, tvb, offset+11,
334 1, ENC_BIG_ENDIAN);
335 offset += 12;
341 static void
342 dissect_fcfcs_gpt (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
344 int offset = 16; /* past the fcct header */
346 if (tree) {
347 if (isreq) {
348 proto_tree_add_string (tree, hf_fcs_portname, tvb, offset, 8,
349 tvb_fcwwn_to_str (tvb, offset));
351 else {
352 proto_tree_add_item (tree, hf_fcs_porttype, tvb, offset+3, 1, ENC_BIG_ENDIAN);
357 static void
358 dissect_fcfcs_gppn (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
360 int offset = 16; /* past the fcct header */
362 if (tree) {
363 if (isreq) {
364 proto_tree_add_string (tree, hf_fcs_portname, tvb, offset, 8,
365 tvb_fcwwn_to_str (tvb, offset));
367 else {
368 proto_tree_add_item (tree, hf_fcs_physportnum, tvb, offset, 4, ENC_NA);
373 static void
374 dissect_fcfcs_gapnl (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
376 int offset = 16; /* past the fcct header */
377 int numelem, i;
379 if (tree) {
380 if (isreq) {
381 proto_tree_add_string (tree, hf_fcs_portname, tvb, offset, 8,
382 tvb_fcwwn_to_str (tvb, offset));
384 else {
385 numelem = tvb_get_ntohl (tvb, offset);
386 proto_tree_add_text (tree, tvb, offset, 4,
387 "Number of Attached Port Entries: %d",
388 numelem);
389 offset += 4;
390 for (i = 0; i < numelem; i++) {
391 proto_tree_add_string (tree, hf_fcs_portname, tvb, offset, 8,
392 tvb_fcwwn_to_str (tvb, offset));
393 proto_tree_add_item (tree, hf_fcs_portflags, tvb, offset+10,
394 1, ENC_BIG_ENDIAN);
395 proto_tree_add_item (tree, hf_fcs_porttype, tvb, offset+11,
396 1, ENC_BIG_ENDIAN);
397 offset += 12;
403 static void
404 dissect_fcfcs_gps (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
406 int offset = 16; /* past the fcct header */
408 if (tree) {
409 if (isreq) {
410 proto_tree_add_string (tree, hf_fcs_portname, tvb, offset, 8,
411 tvb_fcwwn_to_str (tvb, offset));
413 else {
414 proto_tree_add_item (tree, hf_fcs_porttype, tvb, offset+3, 1, ENC_BIG_ENDIAN);
415 proto_tree_add_item (tree, hf_fcs_portstate, tvb, offset+7, 1, ENC_BIG_ENDIAN);
420 static void
421 dissect_fcfcs_gplnl (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
423 int offset = 16; /* past the fcct header */
424 int numelem, i, len;
426 if (tree) {
427 if (isreq) {
428 len = tvb_get_guint8 (tvb, offset);
429 proto_tree_add_text (tree, tvb, offset, 1,
430 "Platform Name Length: %d", len);
431 proto_tree_add_item (tree, hf_fcs_platformname, tvb, offset+1,
432 len, ENC_NA);
434 else {
435 numelem = tvb_get_ntohl (tvb, offset);
436 proto_tree_add_text (tree, tvb, offset, 4,
437 "Number of Platform Node Name Entries: %d",
438 numelem);
439 offset += 4;
440 for (i = 0; i < numelem; i++) {
441 proto_tree_add_string (tree, hf_fcs_platformnname, tvb, offset,
442 8, tvb_fcwwn_to_str (tvb, offset));
443 offset += 8;
449 static void
450 dissect_fcfcs_gplt (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
452 int offset = 16; /* past the fcct header */
453 int len;
455 if (tree) {
456 if (isreq) {
457 len = tvb_get_guint8 (tvb, offset);
458 proto_tree_add_text (tree, tvb, offset, 1,
459 "Platform Name Length: %d", len);
460 proto_tree_add_item (tree, hf_fcs_platformname, tvb, offset+1,
461 len, ENC_NA);
463 else {
464 proto_tree_add_item (tree, hf_fcs_platformtype, tvb, offset+3,
465 1, ENC_BIG_ENDIAN);
470 static void
471 dissect_fcfcs_gplml (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
473 int offset = 16; /* past the fcct header */
474 int numelem, i, len;
476 if (tree) {
477 if (isreq) {
478 len = tvb_get_guint8 (tvb, offset);
479 proto_tree_add_text (tree, tvb, offset, 1,
480 "Platform Name Length: %d", len);
481 proto_tree_add_item (tree, hf_fcs_platformname, tvb, offset+1,
482 len, ENC_NA);
484 else {
485 numelem = tvb_get_ntohl (tvb, offset);
486 proto_tree_add_text (tree, tvb, offset, 4,
487 "Number of Mgmt. Address Entries: %d",
488 numelem);
489 offset += 4;
490 for (i = 0; i < numelem; i++) {
491 len = tvb_get_guint8 (tvb, offset);
492 proto_tree_add_text (tree, tvb, offset, 1,
493 "Mgmt Address Length: %d",
494 len);
495 proto_tree_add_item (tree, hf_fcs_platformaddr, tvb, offset+1,
496 len, ENC_ASCII|ENC_NA);
497 offset += 256;
503 static void
504 dissect_fcfcs_gnpl (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
506 int offset = 16; /* past the fcct header */
507 int len;
509 if (tree) {
510 if (isreq) {
511 proto_tree_add_string (tree, hf_fcs_platformnname, tvb, offset, 8,
512 tvb_fcwwn_to_str (tvb, offset));
514 else {
515 len = tvb_get_guint8 (tvb, offset);
516 proto_tree_add_text (tree, tvb, offset, 1,
517 "Platform Name Length: %d", len);
518 proto_tree_add_item (tree, hf_fcs_platformname, tvb, offset+1,
519 len, ENC_NA);
524 static void
525 dissect_fcfcs_gpnl (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
527 int offset = 16; /* past the fcct header */
528 int numelem, i, len;
530 if (tree) {
531 if (!isreq) {
532 numelem = tvb_get_ntohl (tvb, offset);
534 proto_tree_add_text (tree, tvb, offset, 4,
535 "Number of Platform Name Entries: %d",
536 numelem);
537 offset += 4;
538 for (i = 0; i < numelem; i++) {
539 len = tvb_get_guint8 (tvb, offset);
540 proto_tree_add_text (tree, tvb, offset, 1,
541 "Platform Name Length: %d",
542 len);
543 proto_tree_add_item (tree, hf_fcs_platformname, tvb, offset+1,
544 len, ENC_NA);
545 offset += 256;
551 static void
552 dissect_fcfcs_rieln (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
554 int offset = 16; /* past the fc_ct header */
555 int len;
557 if (tree) {
558 if (isreq) {
559 proto_tree_add_string (tree, hf_fcs_iename, tvb, offset, 8,
560 tvb_fcwwn_to_str (tvb, offset));
561 len = tvb_get_guint8 (tvb, offset+8);
562 proto_tree_add_text (tree, tvb, offset+8, 1,
563 "Logical Name Length: %d", len);
564 proto_tree_add_item (tree, hf_fcs_lname, tvb, offset+9, len, ENC_ASCII|ENC_NA);
569 static void
570 dissect_fcfcs_rpl (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
572 int offset = 16; /* past the fc_ct header */
573 int numelem, i, len;
575 if (tree) {
576 if (isreq) {
577 len = tvb_get_guint8 (tvb, offset);
578 proto_tree_add_text (tree, tvb, offset, 1,
579 "Platform Name Length: %d", len);
580 proto_tree_add_item (tree, hf_fcs_platformname, tvb, offset+1,
581 len, ENC_NA);
582 proto_tree_add_item (tree, hf_fcs_platformtype, tvb, offset+256, 4,
583 ENC_BIG_ENDIAN);
584 numelem = tvb_get_ntohl (tvb, offset+260);
585 proto_tree_add_text (tree, tvb, offset+260, 4,
586 "Number of Mgmt. Addr Entries: %d", numelem);
587 offset += 264;
588 for (i = 0; i < numelem; i++) {
589 len = tvb_get_guint8 (tvb, offset);
590 proto_tree_add_text (tree, tvb, offset, 1,
591 "Mgmt. Addr Length: %d", len);
592 proto_tree_add_item (tree, hf_fcs_mgmtaddr, tvb, offset+1,
593 len, ENC_ASCII|ENC_NA);
594 offset += 256;
597 numelem = tvb_get_ntohl (tvb, offset);
598 proto_tree_add_text (tree, tvb, offset, 4,
599 "Number of Platform Node Name Entries: %d",
600 numelem);
601 offset += 4;
602 for (i = 0; i < numelem; i++) {
603 proto_tree_add_string (tree, hf_fcs_platformnname, tvb, offset,
604 8, tvb_fcwwn_to_str (tvb, offset));
605 offset += 8;
611 static void
612 dissect_fcfcs_rpln (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
614 int offset = 16; /* past the fc_ct header */
615 int len;
617 if (tree) {
618 if (isreq) {
619 len = tvb_get_guint8 (tvb, offset);
620 proto_tree_add_text (tree, tvb, offset, 1,
621 "Platform Name Length: %d", len);
622 proto_tree_add_item (tree, hf_fcs_platformname, tvb, offset+1,
623 len, ENC_NA);
624 proto_tree_add_string (tree, hf_fcs_platformnname, tvb, offset+256,
625 8, tvb_fcwwn_to_str (tvb, offset+256));
630 static void
631 dissect_fcfcs_rplt (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
633 int offset = 16; /* past the fc_ct header */
634 int len;
636 if (tree) {
637 if (isreq) {
638 len = tvb_get_guint8 (tvb, offset);
639 proto_tree_add_text (tree, tvb, offset, 1,
640 "Platform Name Length: %d", len);
641 proto_tree_add_item (tree, hf_fcs_platformname, tvb, offset+1,
642 len, ENC_NA);
643 proto_tree_add_item (tree, hf_fcs_platformtype, tvb, offset+256,
644 4, ENC_BIG_ENDIAN);
649 static void
650 dissect_fcfcs_rplm (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
652 int offset = 16; /* past the fc_ct header */
653 int len;
655 if (tree) {
656 if (isreq) {
657 len = tvb_get_guint8 (tvb, offset);
658 proto_tree_add_text (tree, tvb, offset, 1,
659 "Platform Name Length: %d", len);
660 proto_tree_add_item (tree, hf_fcs_platformname, tvb, offset+1,
661 len, ENC_NA);
662 len = tvb_get_guint8 (tvb, offset+256);
663 proto_tree_add_text (tree, tvb, offset+256, 1,
664 "Platform Mgmt. Address Length: %d", len);
665 proto_tree_add_item (tree, hf_fcs_platformaddr, tvb, offset+257,
666 len, ENC_ASCII|ENC_NA);
671 static void
672 dissect_fcfcs_dpl (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
674 int offset = 16; /* past the fc_ct header */
675 int len;
677 if (tree) {
678 if (isreq) {
679 len = tvb_get_guint8 (tvb, offset);
680 proto_tree_add_text (tree, tvb, offset, 1,
681 "Platform Name Length: %d", len);
682 proto_tree_add_item (tree, hf_fcs_platformname, tvb, offset+1,
683 len, ENC_NA);
688 static void
689 dissect_fcfcs_dpln (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
691 int offset = 16; /* past the fc_ct header */
693 if (tree) {
694 if (isreq) {
695 proto_tree_add_string (tree, hf_fcs_platformnname, tvb, offset, 8,
696 tvb_fcwwn_to_str (tvb, offset));
701 static void
702 dissect_fcfcs_dplml (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
704 int offset = 16; /* past the fc_ct header */
705 int len;
707 if (tree) {
708 if (isreq) {
709 len = tvb_get_guint8 (tvb, offset);
710 proto_tree_add_text (tree, tvb, offset, 1,
711 "Platform Name Length: %d", len);
712 proto_tree_add_item (tree, hf_fcs_platformname, tvb, offset+1,
713 len, ENC_NA);
718 static void
719 dissect_fcfcs_gcap (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
721 int offset = 16; /* past the fc_ct header */
722 int numrec, i;
723 guint8 subtype;
725 if (tree) {
726 if (!isreq) {
727 numrec = tvb_get_ntohl (tvb, offset);
728 proto_tree_add_item (tree, hf_fcs_numcap, tvb, offset, 4, ENC_BIG_ENDIAN);
730 offset += 4;
731 for (i = 0; i < numrec; i++) {
732 subtype = tvb_get_guint8 (tvb, offset);
733 proto_tree_add_uint (tree, hf_fcs_mgmt_subtype, tvb, offset,
734 1, subtype);
736 proto_tree_add_item (tree, hf_fcs_vnd_capmask, tvb, offset+1,
737 3, ENC_BIG_ENDIAN);
738 if (subtype == FCCT_GSSUBTYPE_FCS) {
739 proto_tree_add_item (tree, hf_fcs_fcsmask, tvb, offset+4,
740 4, ENC_BIG_ENDIAN);
742 else if (subtype == FCCT_GSSUBTYPE_UNS) {
743 proto_tree_add_item (tree, hf_fcs_unsmask, tvb, offset+4,
744 4, ENC_BIG_ENDIAN);
746 offset += 8;
752 static void
753 dissect_fcfcs_rjt (tvbuff_t *tvb, proto_tree *tree)
755 int offset = 0;
757 if (tree) {
758 proto_tree_add_item (tree, hf_fcs_reason, tvb, offset+13, 1, ENC_BIG_ENDIAN);
759 proto_tree_add_item (tree, hf_fcs_rjtdetail, tvb, offset+14, 1,
760 ENC_BIG_ENDIAN);
761 proto_tree_add_item (tree, hf_fcs_vendor, tvb, offset+15, 1, ENC_BIG_ENDIAN);
766 static void
767 dissect_fcfcs (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
770 /* Set up structures needed to add the protocol subtree and manage it */
771 int offset = 0;
772 proto_item *ti;
773 proto_tree *fcfcs_tree = NULL;
774 fc_ct_preamble cthdr;
775 gboolean isreq = 1;
776 conversation_t *conversation;
777 fcfcs_conv_data_t *cdata;
778 fcfcs_conv_key_t ckey, *req_key;
779 int opcode,
780 failed_opcode = 0;
782 /* Make entries in Protocol column and Info column on summary display */
783 col_set_str(pinfo->cinfo, COL_PROTOCOL, "FC-FCS");
785 if (tree) {
786 ti = proto_tree_add_protocol_format (tree, proto_fcfcs, tvb, 0,
787 tvb_reported_length (tvb),
788 "FCS");
789 fcfcs_tree = proto_item_add_subtree (ti, ett_fcfcs);
792 tvb_memcpy (tvb, (guint8 *)&cthdr, offset, FCCT_PRMBL_SIZE);
793 cthdr.revision = tvb_get_guint8 (tvb, offset);
794 cthdr.in_id = tvb_get_ntoh24 (tvb, offset+1);
795 cthdr.opcode = g_ntohs (cthdr.opcode);
796 opcode = tvb_get_ntohs (tvb, offset+8);
797 cthdr.maxres_size = g_ntohs (cthdr.maxres_size);
799 if ((opcode != FCCT_MSG_ACC) && (opcode != FCCT_MSG_RJT)) {
800 conversation = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst,
801 pinfo->ptype, pinfo->oxid,
802 pinfo->rxid, NO_PORT2);
803 if (!conversation) {
804 conversation = conversation_new (pinfo->fd->num, &pinfo->src, &pinfo->dst,
805 pinfo->ptype, pinfo->oxid,
806 pinfo->rxid, NO_PORT2);
809 ckey.conv_idx = conversation->index;
811 cdata = (fcfcs_conv_data_t *)g_hash_table_lookup (fcfcs_req_hash,
812 &ckey);
813 if (cdata) {
814 /* Since we never free the memory used by an exchange, this maybe a
815 * case of another request using the same exchange as a previous
816 * req.
818 cdata->opcode = opcode;
820 else {
821 req_key = wmem_new(wmem_file_scope(), fcfcs_conv_key_t);
822 req_key->conv_idx = conversation->index;
824 cdata = wmem_new(wmem_file_scope(), fcfcs_conv_data_t);
825 cdata->opcode = opcode;
827 g_hash_table_insert (fcfcs_req_hash, req_key, cdata);
829 col_add_str (pinfo->cinfo, COL_INFO,
830 val_to_str (opcode, fc_fcs_opcode_abbrev_val, "0x%x"));
832 else {
833 /* Opcode is ACC or RJT */
834 conversation = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst,
835 pinfo->ptype, pinfo->oxid,
836 pinfo->rxid, NO_PORT2);
837 isreq = 0;
838 if (!conversation) {
839 if (opcode == FCCT_MSG_ACC) {
840 col_add_str (pinfo->cinfo, COL_INFO,
841 val_to_str (opcode, fc_fcs_opcode_abbrev_val,
842 "0x%x"));
843 /* No record of what this accept is for. Can't decode */
844 proto_tree_add_text (fcfcs_tree, tvb, 0, tvb_length (tvb),
845 "No record of Exchg. Unable to decode MSG_ACC/RJT");
846 return;
849 else {
850 ckey.conv_idx = conversation->index;
852 cdata = (fcfcs_conv_data_t *)g_hash_table_lookup (fcfcs_req_hash,
853 &ckey);
855 if (cdata != NULL) {
856 if (opcode == FCCT_MSG_ACC)
857 opcode = cdata->opcode;
858 else
859 failed_opcode = cdata->opcode;
862 if (opcode != FCCT_MSG_RJT) {
863 col_add_fstr (pinfo->cinfo, COL_INFO, "MSG_ACC (%s)",
864 val_to_str (opcode, fc_fcs_opcode_abbrev_val,
865 "0x%x"));
867 else {
868 col_add_fstr (pinfo->cinfo, COL_INFO, "MSG_RJT (%s)",
869 val_to_str (failed_opcode,
870 fc_fcs_opcode_abbrev_val,
871 "0x%x"));
874 if (tree) {
875 if ((cdata == NULL) && (opcode != FCCT_MSG_RJT)) {
876 /* No record of what this accept is for. Can't decode */
877 proto_tree_add_text (fcfcs_tree, tvb, 0, tvb_length (tvb),
878 "No record of Exchg. Unable to decode MSG_ACC/RJT");
879 return;
886 if (tree) {
887 proto_tree_add_item (fcfcs_tree, hf_fcs_opcode, tvb, offset+8, 2, ENC_BIG_ENDIAN);
888 proto_tree_add_item (fcfcs_tree, hf_fcs_maxres_size, tvb, offset+10,
889 2, ENC_BIG_ENDIAN);
892 switch (opcode) {
893 case FCCT_MSG_RJT:
894 dissect_fcfcs_rjt (tvb, fcfcs_tree);
895 break;
896 case FCFCS_GIEL:
897 dissect_fcfcs_giel (tvb, fcfcs_tree, isreq);
898 break;
899 case FCFCS_GIET:
900 dissect_fcfcs_giet (tvb, fcfcs_tree, isreq);
901 break;
902 case FCFCS_GDID:
903 dissect_fcfcs_gdid (tvb, fcfcs_tree, isreq);
904 break;
905 case FCFCS_GMID:
906 dissect_fcfcs_gmid (tvb, fcfcs_tree, isreq);
907 break;
908 case FCFCS_GFN:
909 dissect_fcfcs_gfn (tvb, fcfcs_tree, isreq);
910 break;
911 case FCFCS_GIELN:
912 dissect_fcfcs_gieln (tvb, fcfcs_tree, isreq);
913 break;
914 case FCFCS_GMAL:
915 dissect_fcfcs_gmal (tvb, fcfcs_tree, isreq);
916 break;
917 case FCFCS_GIEIL:
918 dissect_fcfcs_gieil (tvb, fcfcs_tree, isreq);
919 break;
920 case FCFCS_GPL:
921 dissect_fcfcs_gpl (tvb, fcfcs_tree, isreq);
922 break;
923 case FCFCS_GPT:
924 dissect_fcfcs_gpt (tvb, fcfcs_tree, isreq);
925 break;
926 case FCFCS_GPPN:
927 dissect_fcfcs_gppn (tvb, fcfcs_tree, isreq);
928 break;
929 case FCFCS_GAPNL:
930 dissect_fcfcs_gapnl (tvb, fcfcs_tree, isreq);
931 break;
932 case FCFCS_GPS:
933 dissect_fcfcs_gps (tvb, fcfcs_tree, isreq);
934 break;
935 case FCFCS_GPLNL:
936 dissect_fcfcs_gplnl (tvb, fcfcs_tree, isreq);
937 break;
938 case FCFCS_GPLT:
939 dissect_fcfcs_gplt (tvb, fcfcs_tree, isreq);
940 break;
941 case FCFCS_GPLML:
942 dissect_fcfcs_gplml (tvb, fcfcs_tree, isreq);
943 break;
944 case FCFCS_GNPL:
945 dissect_fcfcs_gnpl (tvb, fcfcs_tree, isreq);
946 break;
947 case FCFCS_GPNL:
948 dissect_fcfcs_gpnl (tvb, fcfcs_tree, isreq);
949 break;
950 case FCFCS_RIELN:
951 dissect_fcfcs_rieln (tvb, fcfcs_tree, isreq);
952 break;
953 case FCFCS_RPL:
954 dissect_fcfcs_rpl (tvb, fcfcs_tree, isreq);
955 break;
956 case FCFCS_RPLN:
957 dissect_fcfcs_rpln (tvb, fcfcs_tree, isreq);
958 break;
959 case FCFCS_RPLT:
960 dissect_fcfcs_rplt (tvb, fcfcs_tree, isreq);
961 break;
962 case FCFCS_RPLM:
963 dissect_fcfcs_rplm (tvb, fcfcs_tree, isreq);
964 break;
965 case FCFCS_DPL:
966 dissect_fcfcs_dpl (tvb, fcfcs_tree, isreq);
967 break;
968 case FCFCS_DPLN:
969 dissect_fcfcs_dpln (tvb, fcfcs_tree, isreq);
970 break;
971 case FCFCS_DPLML:
972 dissect_fcfcs_dplml (tvb, fcfcs_tree, isreq);
973 break;
974 case FCFCS_GCAP:
975 dissect_fcfcs_gcap (tvb, fcfcs_tree, isreq);
976 break;
977 default:
978 call_dissector (data_handle, tvb, pinfo, fcfcs_tree);
979 break;
983 /* Register the protocol with Wireshark */
985 void
986 proto_register_fcfcs (void)
989 static hf_register_info hf[] = {
990 { &hf_fcs_opcode,
991 {"Opcode", "fcs.opcode", FT_UINT16, BASE_HEX,
992 VALS (fc_fcs_opcode_val), 0x0, NULL, HFILL}},
993 { &hf_fcs_iename,
994 {"Interconnect Element Name", "fcs.ie.name", FT_STRING, BASE_NONE,
995 NULL, 0x0, NULL, HFILL}},
996 { &hf_fcs_ietype,
997 {"Interconnect Element Type", "fcs.ie.type", FT_UINT8, BASE_HEX,
998 VALS (fc_fcs_ietype_val), 0x0, NULL, HFILL}},
999 { &hf_fcs_iedomainid,
1000 {"Interconnect Element Domain ID", "fcs.ie.domainid", FT_UINT8,
1001 BASE_HEX, NULL, 0x0, NULL, HFILL}},
1002 { &hf_fcs_mgmtid,
1003 {"Interconnect Element Mgmt. ID", "fcs.ie.mgmtid", FT_STRING,
1004 BASE_NONE, NULL, 0x0, NULL, HFILL}},
1005 { &hf_fcs_fabricname,
1006 {"Interconnect Element Fabric Name", "fcs.ie.fname", FT_STRING,
1007 BASE_NONE, NULL, 0x0, NULL, HFILL}},
1008 { &hf_fcs_mgmtaddr,
1009 {"Interconnect Element Mgmt. Address", "fcs.ie.mgmtaddr", FT_STRING,
1010 BASE_NONE, NULL, 0x0, NULL, HFILL}},
1011 { &hf_fcs_lname,
1012 {"Interconnect Element Logical Name", "fcs.ie.logname", FT_STRING,
1013 BASE_NONE, NULL, 0x0, NULL, HFILL}},
1014 { &hf_fcs_vendorname,
1015 {"Vendor Name", "fcs.vendorname", FT_STRING, BASE_NONE, NULL, 0x0, NULL,
1016 HFILL}},
1017 { &hf_fcs_modelname,
1018 {"Model Name/Number", "fcs.modelname", FT_STRING, BASE_NONE, NULL,
1019 0x0, NULL, HFILL}},
1020 { &hf_fcs_portname,
1021 {"Port Name", "fcs.port.name", FT_STRING, BASE_NONE, NULL, 0x0, NULL,
1022 HFILL}},
1023 { &hf_fcs_portmodtype,
1024 {"Port Module Type", "fcs.port.moduletype", FT_UINT8, BASE_HEX,
1025 VALS (fc_fcs_port_modtype_val), 0x0, NULL, HFILL}},
1026 { &hf_fcs_porttxtype,
1027 {"Port TX Type", "fcs.port.txtype", FT_UINT8, BASE_HEX,
1028 VALS (fc_fcs_port_txtype_val), 0x0, NULL, HFILL}},
1029 { &hf_fcs_porttype,
1030 {"Port Type", "fcs.port.type", FT_UINT8, BASE_HEX,
1031 VALS (fc_fcs_port_type_val), 0x0, NULL, HFILL}},
1032 { &hf_fcs_physportnum,
1033 {"Physical Port Number", "fcs.port.physportnum", FT_BYTES, BASE_NONE,
1034 NULL, 0x0, NULL, HFILL}},
1035 { &hf_fcs_portflags,
1036 {"Port Flags", "fcs.port.flags", FT_BOOLEAN, BASE_NONE,
1037 TFS (&fc_fcs_portflags_tfs), 0x0, NULL, HFILL}},
1038 { &hf_fcs_portstate,
1039 {"Port State", "fcs.port.state", FT_UINT8, BASE_HEX,
1040 VALS (fc_fcs_port_state_val), 0x0, NULL, HFILL}},
1041 { &hf_fcs_platformname,
1042 {"Platform Name", "fcs.platform.name", FT_BYTES, BASE_NONE, NULL, 0x0,
1043 NULL, HFILL}},
1044 { &hf_fcs_platformnname,
1045 {"Platform Node Name", "fcs.platform.nodename", FT_STRING, BASE_NONE,
1046 NULL, 0x0, NULL, HFILL}},
1047 { &hf_fcs_platformtype,
1048 {"Platform Type", "fcs.platform.type", FT_UINT8, BASE_HEX,
1049 VALS (fc_fcs_plat_type_val), 0x0, NULL, HFILL}},
1050 { &hf_fcs_platformaddr,
1051 {"Management Address", "fcs.platform.mgmtaddr", FT_STRING, BASE_NONE,
1052 NULL, 0x0, NULL, HFILL}},
1053 { &hf_fcs_reason,
1054 {"Reason Code", "fcs.reason", FT_UINT8, BASE_HEX,
1055 VALS (fc_ct_rjt_code_vals), 0x0, NULL, HFILL}},
1056 { &hf_fcs_rjtdetail,
1057 {"Reason Code Explanantion", "fcs.reasondet", FT_UINT8, BASE_HEX,
1058 VALS (fc_fcs_rjt_code_val), 0x0, NULL, HFILL}},
1059 { &hf_fcs_vendor,
1060 {"Vendor Unique Reject Code", "fcs.err.vendor", FT_UINT8, BASE_HEX,
1061 NULL, 0x0, NULL, HFILL}},
1062 { &hf_fcs_numcap,
1063 {"Number of Capabilities", "fcs.numcap", FT_UINT32, BASE_DEC, NULL,
1064 0x0, NULL, HFILL}},
1065 { &hf_fcs_mgmt_subtype,
1066 {"Management GS Subtype", "fcs.gssubtype", FT_UINT8, BASE_HEX, NULL,
1067 0x0, NULL, HFILL}},
1068 { &hf_fcs_vnd_capmask,
1069 {"Vendor Unique Capability Bitmask", "fcs.vbitmask", FT_UINT24,
1070 BASE_HEX, NULL, 0x0, NULL, HFILL}},
1071 { &hf_fcs_fcsmask,
1072 {"Subtype Capability Bitmask", "fcs.fcsmask", FT_UINT32, BASE_HEX,
1073 VALS (fc_fcs_fcsmask_val), 0x0, NULL, HFILL}},
1074 { &hf_fcs_unsmask,
1075 {"Subtype Capability Bitmask", "fcs.unsmask", FT_UINT32, BASE_HEX,
1076 VALS (fc_fcs_unsmask_val), 0x0, NULL, HFILL}},
1077 { &hf_fcs_maxres_size,
1078 {"Maximum/Residual Size", "fcs.maxres_size", FT_UINT16, BASE_DEC,
1079 NULL, 0x0, NULL, HFILL}},
1080 { &hf_fcs_releasecode,
1081 {"Release Code", "fcs.releasecode", FT_STRING, BASE_NONE, NULL, 0x0,
1082 NULL, HFILL}},
1085 static gint *ett[] = {
1086 &ett_fcfcs,
1089 proto_fcfcs = proto_register_protocol("FC Fabric Configuration Server",
1090 "FC-FCS", "fcs");
1092 proto_register_field_array(proto_fcfcs, hf, array_length(hf));
1093 proto_register_subtree_array(ett, array_length(ett));
1094 register_init_routine (&fcfcs_init_protocol);
1097 void
1098 proto_reg_handoff_fcfcs (void)
1100 dissector_handle_t fcs_handle;
1102 fcs_handle = create_dissector_handle (dissect_fcfcs, proto_fcfcs);
1104 dissector_add_uint("fcct.server", FCCT_GSRVR_FCS, fcs_handle);
1106 data_handle = find_dissector ("data");