2 * Routines for FCIP dissection
4 * Copyright 2001, Dinesh G Dutt (ddutt@cisco.com)
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 #include <epan/packet.h>
32 #include <epan/prefs.h>
34 #define FCIP_ENCAP_HEADER_LEN 28
35 #define FCIP_MIN_HEADER_LEN 16 /* upto frame len field */
36 #define FCIP_IS_SF(pflags) ((pflags & 0x1) == 0x1)
37 #define FCIP_IS_CH(pflags) ((pflags & 0x80) == 0x80)
62 FCENCAP_PROTO_FCIP
= 1,
63 FCENCAP_PROTO_iFCP
= 2
66 static const value_string fcip_eof_vals
[] = {
69 {FCIP_EOFrt
, "EOFrt" },
70 {FCIP_EOFdt
, "EOFdt" },
71 {FCIP_EOFni
, "EOFni" },
72 {FCIP_EOFdti
, "EOFdti" },
73 {FCIP_EOFrti
, "EOFrti" },
78 static const value_string fcip_sof_vals
[] = {
80 {FCIP_SOFi4
, "SOFi4" },
81 {FCIP_SOFi2
, "SOFi2" },
82 {FCIP_SOFi3
, "SOFi3" },
83 {FCIP_SOFn4
, "SOFn4" },
84 {FCIP_SOFn2
, "SOFn2" },
85 {FCIP_SOFn3
, "SOFn3" },
86 {FCIP_SOFc4
, "SOFc4" },
90 static const value_string fcencap_proto_vals
[] = {
91 {FCENCAP_PROTO_FCIP
, "FCIP" },
92 {FCENCAP_PROTO_iFCP
, "iFCP" },
96 static const guint8 fcip_header_8_bytes
[8] = {
97 0x01, 0x01, 0xFE, 0xFE,
98 0x01, 0x01, 0xFE, 0xFE
101 static int proto_fcip
= -1;
103 static int hf_fcip_protocol
= -1;
104 static int hf_fcip_protocol_c
= -1;
105 static int hf_fcip_version
= -1;
106 static int hf_fcip_version_c
= -1;
107 static int hf_fcip_encap_word1
= -1;
108 static int hf_fcip_flags
= -1;
109 static int hf_fcip_flags_c
= -1;
110 static int hf_fcip_framelen
= -1;
111 static int hf_fcip_framelen_c
= -1;
112 static int hf_fcip_tsec
= -1;
113 static int hf_fcip_tusec
= -1;
114 static int hf_fcip_encap_crc
= -1;
115 static int hf_fcip_sof
= -1;
116 static int hf_fcip_sof_c
= -1;
117 static int hf_fcip_eof
= -1;
118 static int hf_fcip_eof_c
= -1;
119 static int hf_fcip_pflags_changed
= -1;
120 static int hf_fcip_pflags_special
= -1;
121 static int hf_fcip_pflags_c
= -1;
122 static int hf_fcip_src_wwn
= -1;
123 static int hf_fcip_dst_wwn
= -1;
124 static int hf_fcip_conn_code
= -1;
125 static int hf_fcip_katov
= -1;
126 static int hf_fcip_src_entity_id
= -1;
127 static int hf_fcip_conn_nonce
= -1;
128 static int hf_fcip_conn_flags
= -1;
130 static int ett_fcip
= -1;
132 static guint fcip_port
= 3225;
133 static gboolean fcip_desegment
= TRUE
;
135 static dissector_handle_t data_handle
;
136 static dissector_handle_t fc_handle
;
138 /* This routine attempts to locate the position of the next header in the
142 get_next_fcip_header_offset (tvbuff_t
*tvb
, packet_info
*pinfo
, gint offset
)
144 gint bytes_remaining
= tvb_length_remaining (tvb
, offset
);
147 fcip_eof_t eof
, eofc
;
150 * As per the FCIP standard, the following tests must PASS:
151 * 1) Frame Length field validation -- 15 < Frame Length < 545;
152 * 2) Comparison of Frame Length field to its ones complement; and
153 * 3) A valid EOF is found in the word preceding the start of the next
154 * FCIP header as indicated by the Frame Length field, to be tested
156 * 1) Bits 24-31 and 16-23 contain identical legal EOF values (the
157 * list of legal EOF values is in the FC Frame Encapsulation
159 * 2) Bits 8-15 and 0-7 contain the ones complement of the EOF
160 * value found in bits 24-31.
162 * As per the FCIP standard, in addition, at least 3 of the following set
163 * of tests must be performed to identify that we've located the start of
165 * a) Protocol# ones complement field (1 test);
166 * b) Version ones complement field (1 test);
167 * c) Replication of encapsulation word 0 in word 1 (1 test);
168 * d) Reserved field and its ones complement (2 tests);
169 * e) Flags field and its ones complement (2 tests);
170 * f) CRC field is equal to zero (1 test); (DONT DO THIS TEST!)
171 * g) SOF fields and ones complement fields (4 tests);
172 * h) Format and values of FC header (1 test);
173 * i) CRC of FC Frame (2 tests);
174 * j) FC Frame Encapsulation header information in the next FCIP Frame
177 * At least 3 of the 16 tests listed above SHALL be performed. Failure
178 * of any of the above tests actually performed SHALL indicate an
179 * encapsulation error and the FC Frame SHALL NOT be forwarded on to
183 NXT_BYTE
: while (bytes_remaining
) {
184 if (bytes_remaining
< FCIP_ENCAP_HEADER_LEN
) {
185 if(fcip_desegment
&& pinfo
->can_desegment
) {
187 * This frame doesn't have all of the data for
188 * the message header, but we can do reassembly on it.
190 * Tell the TCP dissector where the data for this
191 * message starts in the data it handed us, and that we need
192 * "some more data." Don't tell it exactly how many bytes
193 * we need because if/when we ask for even more (after the
194 * header) that will break reassembly.
196 pinfo
->desegment_offset
= offset
;
197 pinfo
->desegment_len
= DESEGMENT_ONE_MORE_SEGMENT
;
202 /* I check that we have a valid header before checking for the frame
203 * length and the other initial tests.
209 if (tvb_memeql(tvb
, offset
, fcip_header_8_bytes
, 8) != 0) {
215 flen
= (tvb_get_ntohs (tvb
, offset
+12)) & 0x03FF;
216 frame_len
= (tvb_get_ntohs (tvb
, offset
+12) & 0x03FF)*4;
218 if ((flen
< 15) || (flen
> 545)) {
219 /* Frame length check failed. Skip byte and try again */
225 flen1
= (tvb_get_ntohs (tvb
, offset
+14)) & 0x03FF;
227 if ((flen
& 0x03FF) != ((~flen1
)&0x03FF)) {
228 /* frame_len and its one's complement are not the same */
234 /* Valid EOF check */
235 if (tvb_bytes_exist (tvb
, offset
+(frame_len
-1)*4, 4)) {
236 eof
= (fcip_eof_t
)tvb_get_guint8 (tvb
, offset
+(frame_len
-1)*4);
237 eofc
= (fcip_eof_t
)tvb_get_guint8 (tvb
, offset
+(frame_len
-1)*4+2);
239 if ((eof
!= FCIP_EOFn
) && (eof
!= FCIP_EOFt
) && (eof
!= FCIP_EOFrt
)
240 && (eof
!= FCIP_EOFdt
) && (eof
!= FCIP_EOFni
) &&
241 (eof
!= FCIP_EOFdti
) && (eof
!= FCIP_EOFrti
) &&
242 (eof
!= FCIP_EOFa
)) {
248 if ((eof
!= ~eofc
) ||
249 (eof
!= tvb_get_guint8 (tvb
, offset
+(frame_len
-1)*4+1)) ||
250 (eofc
!= tvb_get_guint8 (tvb
, offset
+(frame_len
-1)*4+3))) {
258 if ((tvb_get_guint8 (tvb
, offset
+9) != 0) ||
259 (tvb_get_guint8 (tvb
, offset
+11) != 0xFF)) {
270 * We dont test this since some implementations actually provide
274 if (bytes_remaining
>= (frame_len
)) {
275 if (tvb_bytes_exist (tvb
, offset
+frame_len
, 8)) {
276 /* The start of the next header matches what we wish to see */
277 if (tvb_memeql (tvb
, offset
+frame_len
, fcip_header_8_bytes
,
292 if(fcip_desegment
&& pinfo
->can_desegment
) {
294 * This frame doesn't have all of the data for
295 * this message, but we can do reassembly on it.
297 * Tell the TCP dissector where the data for this
298 * message starts in the data it handed us, and
299 * how many more bytes we need, and return.
301 pinfo
->desegment_offset
= offset
;
302 pinfo
->desegment_len
= frame_len
- bytes_remaining
;
311 return (-1); /* Unable to find FCIP header */
315 dissect_fcencap_header (tvbuff_t
*tvb
, proto_tree
*tree
, gint offset
)
317 guint8 protocol
= tvb_get_guint8 (tvb
, offset
);
320 proto_tree_add_uint (tree
, hf_fcip_protocol
, tvb
, offset
, 1, protocol
);
321 proto_tree_add_item (tree
, hf_fcip_version
, tvb
, offset
+1, 1, ENC_BIG_ENDIAN
);
322 proto_tree_add_item (tree
, hf_fcip_protocol_c
, tvb
, offset
+2, 1, ENC_BIG_ENDIAN
);
323 proto_tree_add_item (tree
, hf_fcip_version_c
, tvb
, offset
+3, 1, ENC_BIG_ENDIAN
);
325 if (protocol
== FCENCAP_PROTO_FCIP
) {
326 proto_tree_add_item (tree
, hf_fcip_encap_word1
, tvb
, offset
+4,
328 proto_tree_add_item (tree
, hf_fcip_pflags_changed
, tvb
, offset
+8,
330 proto_tree_add_item (tree
, hf_fcip_pflags_special
, tvb
, offset
+8,
332 proto_tree_add_item (tree
, hf_fcip_pflags_c
, tvb
, offset
+10, 1, ENC_BIG_ENDIAN
);
335 /* XXX - break out CRCV flag. */
336 proto_tree_add_item (tree
, hf_fcip_flags
, tvb
, offset
+12, 1, ENC_BIG_ENDIAN
);
337 proto_tree_add_item (tree
, hf_fcip_framelen
, tvb
, offset
+12, 2, ENC_BIG_ENDIAN
);
338 proto_tree_add_item (tree
, hf_fcip_flags_c
, tvb
, offset
+14, 1, ENC_BIG_ENDIAN
);
339 proto_tree_add_item (tree
, hf_fcip_framelen_c
, tvb
, offset
+14, 2, ENC_BIG_ENDIAN
);
340 proto_tree_add_item (tree
, hf_fcip_tsec
, tvb
, offset
+16, 4, ENC_BIG_ENDIAN
);
341 proto_tree_add_item (tree
, hf_fcip_tusec
, tvb
, offset
+20, 4, ENC_BIG_ENDIAN
);
342 /* XXX - check CRC if CRCV is set? */
343 proto_tree_add_item (tree
, hf_fcip_encap_crc
, tvb
, offset
+24, 4, ENC_BIG_ENDIAN
);
348 dissect_fcip_sf (tvbuff_t
*tvb
, proto_tree
*tree
, gint offset
)
351 proto_tree_add_string (tree
, hf_fcip_src_wwn
, tvb
, offset
, 8,
352 tvb_fcwwn_to_str (tvb
, offset
));
353 proto_tree_add_item (tree
, hf_fcip_src_entity_id
, tvb
, offset
+8, 8,
355 proto_tree_add_item (tree
, hf_fcip_conn_nonce
, tvb
, offset
+16, 8,
357 /* XXX - break out these flags */
358 proto_tree_add_item (tree
, hf_fcip_conn_flags
, tvb
, offset
+24, 1, ENC_BIG_ENDIAN
);
359 proto_tree_add_item (tree
, hf_fcip_conn_code
, tvb
, offset
+26, 2, ENC_BIG_ENDIAN
);
360 proto_tree_add_string (tree
, hf_fcip_dst_wwn
, tvb
, offset
+30, 8,
361 tvb_fcwwn_to_str (tvb
, offset
+30));
362 proto_tree_add_item (tree
, hf_fcip_katov
, tvb
, offset
+38, 4, ENC_BIG_ENDIAN
);
367 dissect_fcip (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
373 gint bytes_remaining
= tvb_length (tvb
);
374 guint8 pflags
, sof
= 0, eof
= 0;
375 /* Set up structures needed to add the protocol subtree and manage it */
377 proto_tree
*fcip_tree
= NULL
;
380 if (bytes_remaining
< FCIP_ENCAP_HEADER_LEN
) {
385 ((pinfo
->srcport
!= fcip_port
) && (pinfo
->destport
!= fcip_port
))) {
389 while (bytes_remaining
> FCIP_ENCAP_HEADER_LEN
) {
390 if ((offset
= get_next_fcip_header_offset (tvb
, pinfo
, offset
)) == -1) {
393 else if (offset
== -2) {
394 /* We need more data to desegment */
399 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "FCIP");
401 frame_len
= (tvb_get_ntohs (tvb
, offset
+12) & 0x03FF)*4;
403 if (bytes_remaining
< frame_len
) {
404 if(fcip_desegment
&& pinfo
->can_desegment
) {
406 * This frame doesn't have all of the data for
407 * this message, but we can do reassembly on it.
409 * Tell the TCP dissector where the data for this
410 * message starts in the data it handed us, and
411 * how many more bytes we need, and return.
413 pinfo
->desegment_offset
= offset
;
414 pinfo
->desegment_len
= frame_len
- bytes_remaining
;
419 pflags
= tvb_get_guint8 (tvb
, start
+8);
422 if (FCIP_IS_SF (pflags
)) {
423 ti
= proto_tree_add_protocol_format (tree
, proto_fcip
, tvb
, 0,
424 FCIP_ENCAP_HEADER_LEN
,
427 else if (tvb_bytes_exist (tvb
, offset
, offset
+frame_len
-4)) {
428 sof
= tvb_get_guint8 (tvb
, offset
+FCIP_ENCAP_HEADER_LEN
);
429 eof
= tvb_get_guint8 (tvb
, offset
+frame_len
- 4);
431 ti
= proto_tree_add_protocol_format (tree
, proto_fcip
, tvb
, 0,
432 FCIP_ENCAP_HEADER_LEN
,
434 val_to_str (sof
, fcip_sof_vals
,
436 val_to_str (eof
, fcip_eof_vals
,
440 sof
= tvb_get_guint8 (tvb
, offset
+FCIP_ENCAP_HEADER_LEN
);
442 ti
= proto_tree_add_protocol_format (tree
, proto_fcip
, tvb
, 0,
443 FCIP_ENCAP_HEADER_LEN
,
445 val_to_str (sof
, fcip_sof_vals
,
449 fcip_tree
= proto_item_add_subtree (ti
, ett_fcip
);
450 /* Dissect the Common FC Encap header */
451 dissect_fcencap_header (tvb
, fcip_tree
, offset
);
453 offset
+= FCIP_ENCAP_HEADER_LEN
;
455 if (!FCIP_IS_SF (pflags
)) {
457 proto_tree_add_item (fcip_tree
, hf_fcip_sof
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
458 proto_tree_add_item (fcip_tree
, hf_fcip_sof_c
, tvb
, offset
+2, 1, ENC_BIG_ENDIAN
);
461 offset
+= (frame_len
-FCIP_ENCAP_HEADER_LEN
-4);
462 if (tvb_bytes_exist (tvb
, offset
, 4)) {
463 proto_tree_add_item (fcip_tree
, hf_fcip_eof
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
464 proto_tree_add_item (fcip_tree
, hf_fcip_eof_c
, tvb
, offset
+2, 1, ENC_BIG_ENDIAN
);
469 /* Call the FC Dissector if this is carrying an FC frame */
470 if (!FCIP_IS_SF(pflags
)) {
471 /* Set the SOF/EOF flags in the packet_info header */
475 if ((sof
== FCIP_SOFi3
) || (sof
== FCIP_SOFi2
) || (sof
== FCIP_SOFi4
)) {
476 pinfo
->sof_eof
= PINFO_SOF_FIRST_FRAME
;
478 else if (sof
== FCIP_SOFf
) {
479 pinfo
->sof_eof
= PINFO_SOF_SOFF
;
482 if (eof
!= FCIP_EOFn
) {
483 pinfo
->sof_eof
|= PINFO_EOF_LAST_FRAME
;
485 else if (eof
!= FCIP_EOFt
) {
486 pinfo
->sof_eof
|= PINFO_EOF_INVALID
;
490 /* Special frame bit is not set */
491 next_tvb
= tvb_new_subset_remaining (tvb
, FCIP_ENCAP_HEADER_LEN
+4);
493 call_dissector (fc_handle
, next_tvb
, pinfo
, tree
);
495 else if (data_handle
) {
496 call_dissector (data_handle
, next_tvb
, pinfo
, tree
);
500 col_set_str(pinfo
->cinfo
, COL_INFO
, "Special Frame");
501 if (FCIP_IS_CH (pflags
)) {
502 col_append_str(pinfo
->cinfo
, COL_INFO
, "(Changed)");
505 dissect_fcip_sf (tvb
, fcip_tree
, offset
+4);
508 bytes_remaining
-= frame_len
;
514 /* This is called for those sessions where we have explicitely said
515 this to be FCIP using "Decode As..."
516 In this case we will not check the port number for sanity and just
520 dissect_fcip_handle(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
522 dissect_fcip (tvb
, pinfo
, tree
, FALSE
);
526 dissect_fcip_heur (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
528 return (dissect_fcip (tvb
, pinfo
, tree
, TRUE
));
532 proto_register_fcip (void)
535 /* Setup list of header fields See Section 1.6.1 for details*/
536 static hf_register_info hf
[] = {
538 { "Protocol", "fcip.proto", FT_UINT8
, BASE_DEC
,
539 VALS(fcencap_proto_vals
), 0, NULL
, HFILL
}},
540 { &hf_fcip_protocol_c
,
541 {"Protocol (1's Complement)", "fcip.protoc", FT_UINT8
, BASE_DEC
,
542 NULL
, 0, NULL
, HFILL
}},
544 {"Version", "fcip.version", FT_UINT8
, BASE_DEC
,
545 NULL
, 0, NULL
, HFILL
}},
546 { &hf_fcip_version_c
,
547 {"Version (1's Complement)", "fcip.versionc", FT_UINT8
, BASE_DEC
,
548 NULL
, 0, NULL
, HFILL
}},
549 { &hf_fcip_encap_word1
,
550 {"FCIP Encapsulation Word1", "fcip.encap_word1", FT_UINT32
, BASE_HEX
,
551 NULL
, 0, NULL
, HFILL
}},
553 {"Flags", "fcip.flags", FT_UINT8
, BASE_HEX
,
554 NULL
, 0xFC, NULL
, HFILL
}},
556 {"Flags (1's Complement)", "fcip.flagsc", FT_UINT8
, BASE_HEX
,
557 NULL
, 0xFC, NULL
, HFILL
}},
559 {"Frame Length (in Words)", "fcip.framelen", FT_UINT16
, BASE_DEC
,
560 NULL
, 0x03FF, NULL
, HFILL
}},
561 { &hf_fcip_framelen_c
,
562 {"Frame Length (1's Complement)", "fcip.framelenc", FT_UINT16
, BASE_DEC
,
563 NULL
, 0x03FF, NULL
, HFILL
}},
565 {"Time (secs)", "fcip.tsec", FT_UINT32
, BASE_DEC
,
566 NULL
, 0, NULL
, HFILL
}},
568 {"Time (fraction)", "fcip.tusec", FT_UINT32
, BASE_DEC
,
569 NULL
, 0, NULL
, HFILL
}},
570 { &hf_fcip_encap_crc
,
571 {"CRC", "fcip.encap_crc", FT_UINT32
, BASE_HEX
,
572 NULL
, 0, NULL
, HFILL
}},
574 {"SOF", "fcip.sof", FT_UINT8
, BASE_HEX
,
575 VALS (&fcip_sof_vals
), 0, NULL
, HFILL
}},
577 {"SOF (1's Complement)", "fcip.sofc", FT_UINT8
, BASE_HEX
,
578 NULL
, 0, NULL
, HFILL
}},
580 {"EOF", "fcip.eof", FT_UINT8
, BASE_HEX
,
581 VALS (&fcip_eof_vals
), 0, NULL
, HFILL
}},
583 {"EOF (1's Complement)", "fcip.eofc", FT_UINT8
, BASE_HEX
,
584 NULL
, 0, NULL
, HFILL
}},
585 { &hf_fcip_pflags_changed
,
586 {"Changed Flag", "fcip.pflags.ch", FT_BOOLEAN
, 8,
587 NULL
, 0x80, NULL
, HFILL
}},
588 { &hf_fcip_pflags_special
,
589 {"Special Frame Flag", "fcip.pflags.sf", FT_BOOLEAN
, 8,
590 NULL
, 0x1, NULL
, HFILL
}},
592 {"Pflags (1's Complement)", "fcip.pflagsc", FT_UINT8
, BASE_HEX
,
593 NULL
, 0x0, NULL
, HFILL
}},
595 {"Source Fabric WWN", "fcip.srcwwn", FT_STRING
, BASE_NONE
,
596 NULL
, 0x0, NULL
, HFILL
}},
598 {"Destination Fabric WWN", "fcip.dstwwn", FT_STRING
, BASE_NONE
,
599 NULL
, 0x0, NULL
, HFILL
}},
600 { &hf_fcip_src_entity_id
,
601 {"FC/FCIP Entity Id", "fcip.srcid", FT_BYTES
, BASE_NONE
,
602 NULL
, 0x0, NULL
, HFILL
}},
603 { &hf_fcip_conn_flags
,
604 {"Connection Usage Flags", "fcip.connflags", FT_UINT8
, BASE_HEX
,
605 NULL
, 0x0, NULL
, HFILL
}},
606 { &hf_fcip_conn_code
,
607 {"Connection Usage Code", "fcip.conncode", FT_UINT16
, BASE_HEX
,
608 NULL
, 0x0, NULL
, HFILL
}},
610 {"K_A_TOV", "fcip.katov", FT_UINT32
, BASE_DEC
,
611 NULL
, 0x0, NULL
, HFILL
}},
612 { &hf_fcip_conn_nonce
,
613 {"Connection Nonce", "fcip.nonce", FT_BYTES
, BASE_NONE
,
614 NULL
, 0x0, NULL
, HFILL
}},
617 static gint
*ett
[] = {
621 module_t
*fcip_module
;
623 /* Register the protocol name and description */
624 proto_fcip
= proto_register_protocol("FCIP", "Fibre Channel over IP", "fcip");
626 proto_register_field_array(proto_fcip
, hf
, array_length(hf
));
627 proto_register_subtree_array(ett
, array_length(ett
));
629 fcip_module
= prefs_register_protocol(proto_fcip
, NULL
);
630 prefs_register_bool_preference(fcip_module
,
632 "Reassemble FCIP messages spanning multiple TCP segments",
633 "Whether the FCIP dissector should reassemble messages spanning multiple TCP segments."
634 " To use this option, you must also enable"
635 " \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
637 prefs_register_uint_preference(fcip_module
,
640 "Port number used for FCIP",
646 proto_reg_handoff_fcip (void)
648 dissector_handle_t fcip_handle
;
650 heur_dissector_add("tcp", dissect_fcip_heur
, proto_fcip
);
652 fcip_handle
= create_dissector_handle(dissect_fcip_handle
, proto_fcip
);
653 dissector_add_handle("tcp.port", fcip_handle
);
655 data_handle
= find_dissector("data");
656 fc_handle
= find_dissector("fc");