Use tvb_memeql() and tvb_memcpy().
[metze/wireshark/wip.git] / epan / dissectors / packet-fcip.c
1 /* packet-fcip.c
2  * Routines for FCIP dissection
3  * RFC 3821, RFC 3643
4  * Copyright 2001, Dinesh G Dutt (ddutt@cisco.com)
5  *
6  * $Id$
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
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.
16  *
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.
21  *
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <stdlib.h>
32
33 #include <glib.h>
34
35 #include <epan/packet.h>
36 #include <epan/prefs.h>
37
38 #define FCIP_ENCAP_HEADER_LEN                    28
39 #define FCIP_MIN_HEADER_LEN                      16 /* upto frame len field */
40 #define FCIP_IS_SF(pflags)                       ((pflags & 0x1) == 0x1)
41 #define FCIP_IS_CH(pflags)                       ((pflags & 0x80) == 0x80)
42
43 typedef enum {
44     FCIP_EOFn    = 0x41,
45     FCIP_EOFt    = 0x42,
46     FCIP_EOFrt   = 0x44,
47     FCIP_EOFdt   = 0x46,
48     FCIP_EOFni   = 0x49,
49     FCIP_EOFdti  = 0x4E,
50     FCIP_EOFrti  = 0x4F,
51     FCIP_EOFa    = 0x50
52 } fcip_eof_t;
53
54 typedef enum {
55     FCIP_SOFf    = 0x28,
56     FCIP_SOFi4   = 0x29,
57     FCIP_SOFi2   = 0x2D,
58     FCIP_SOFi3   = 0x2E,
59     FCIP_SOFn4   = 0x31,
60     FCIP_SOFn2   = 0x35,
61     FCIP_SOFn3   = 0x36,
62     FCIP_SOFc4   = 0x39
63 } fcip_sof_t;
64
65 typedef enum {
66     FCENCAP_PROTO_FCIP = 1,
67     FCENCAP_PROTO_iFCP = 2
68 } fcencap_proto_t;
69
70 static const value_string fcip_eof_vals[] = {
71     {FCIP_EOFn, "EOFn" },
72     {FCIP_EOFt, "EOFt" },
73     {FCIP_EOFrt, "EOFrt" },
74     {FCIP_EOFdt, "EOFdt" },
75     {FCIP_EOFni, "EOFni" },
76     {FCIP_EOFdti, "EOFdti" },
77     {FCIP_EOFrti, "EOFrti" },
78     {FCIP_EOFa, "EOFa" },
79     {0, NULL},
80 };
81
82 static const value_string fcip_sof_vals[] = {
83     {FCIP_SOFf, "SOFf" },
84     {FCIP_SOFi4, "SOFi4" },
85     {FCIP_SOFi2, "SOFi2" },
86     {FCIP_SOFi3, "SOFi3" },
87     {FCIP_SOFn4, "SOFn4" },
88     {FCIP_SOFn2, "SOFn2" },
89     {FCIP_SOFn3, "SOFn3" },
90     {FCIP_SOFc4, "SOFc4" },
91     {0, NULL},
92 };
93
94 static const value_string fcencap_proto_vals[] = {
95     {FCENCAP_PROTO_FCIP, "FCIP"},
96     {FCENCAP_PROTO_iFCP, "iFCP"},
97     {0, NULL},
98 };
99
100 static const guint8 fcip_header_8_bytes[8] = {
101     0x01, 0x01, 0xFE, 0xFE,
102     0x01, 0x01, 0xFE, 0xFE
103 };
104
105 static int proto_fcip          = -1;
106
107 static int hf_fcip_protocol    = -1;
108 static int hf_fcip_protocol_c  = -1;
109 static int hf_fcip_version     = -1;
110 static int hf_fcip_version_c   = -1;
111 static int hf_fcip_encap_word1 = -1;
112 static int hf_fcip_flags       = -1;
113 static int hf_fcip_flags_c     = -1;
114 static int hf_fcip_framelen    = -1;
115 static int hf_fcip_framelen_c  = -1;
116 static int hf_fcip_tsec        = -1;
117 static int hf_fcip_tusec       = -1;
118 static int hf_fcip_encap_crc   = -1;
119 static int hf_fcip_sof         = -1;
120 static int hf_fcip_sof_c       = -1;
121 static int hf_fcip_eof         = -1;
122 static int hf_fcip_eof_c       = -1;
123 static int hf_fcip_pflags_changed = -1;
124 static int hf_fcip_pflags_special = -1;
125 static int hf_fcip_pflags_c = -1;
126 static int hf_fcip_src_wwn = -1;
127 static int hf_fcip_dst_wwn = -1;
128 static int hf_fcip_conn_code = -1;
129 static int hf_fcip_katov = -1;
130 static int hf_fcip_src_entity_id = -1;
131 static int hf_fcip_conn_nonce = -1;
132 static int hf_fcip_conn_flags = -1;
133
134 static int ett_fcip            = -1;
135
136 static guint fcip_port         = 3225;
137 static gboolean fcip_desegment = TRUE;
138
139 static dissector_handle_t data_handle;
140 static dissector_handle_t fc_handle;
141
142 /* This routine attempts to locate the position of the next header in the
143  * provided segment
144  */
145 static guint
146 get_next_fcip_header_offset (tvbuff_t *tvb, packet_info *pinfo, gint offset)
147 {
148     gint bytes_remaining = tvb_length_remaining (tvb, offset);
149     gint frame_len;
150     guint16 flen, flen1;
151     fcip_eof_t eof, eofc;
152
153     /*
154      * As per the FCIP standard, the following tests must PASS:
155      * 1)  Frame Length field validation -- 15 < Frame Length < 545;
156      * 2)  Comparison of Frame Length field to its ones complement; and
157      * 3)  A valid EOF is found in the word preceding the start of the next
158      *     FCIP header as indicated by the Frame Length field, to be tested
159      *     as follows:
160      *     1)  Bits 24-31 and 16-23 contain identical legal EOF values (the
161      *         list of legal EOF values is in the FC Frame Encapsulation
162      *         [21]); and
163      *     2)  Bits 8-15 and 0-7 contain the ones complement of the EOF
164      *         value found in bits 24-31.
165      *
166      * As per the FCIP standard, in addition, at least 3 of the following set
167      * of tests must be performed to identify that we've located the start of
168      * an FCIP frame.
169      * a)  Protocol# ones complement field (1 test);
170      * b)  Version ones complement field (1 test);
171      * c)  Replication of encapsulation word 0 in word 1 (1 test);
172      * d)  Reserved field and its ones complement (2 tests);
173      * e)  Flags field and its ones complement (2 tests);
174      *    f)  CRC field is equal to zero (1 test); (DONT DO THIS TEST!)
175      * g)  SOF fields and ones complement fields (4 tests);
176      * h)  Format and values of FC header (1 test);
177      * i)  CRC of FC Frame (2 tests);
178      * j)  FC Frame Encapsulation header information in the next FCIP Frame
179      *     (1 test).
180      *
181      * At least 3 of the 16 tests listed above SHALL be performed. Failure
182      * of any of the above tests actually performed SHALL indicate an
183      * encapsulation error and the FC Frame SHALL NOT be forwarded on to
184      * the FC Entity.
185      */
186
187 NXT_BYTE: while (bytes_remaining) {
188         if (bytes_remaining < FCIP_ENCAP_HEADER_LEN) {
189             if(fcip_desegment && pinfo->can_desegment) {
190                 /*
191                  * This frame doesn't have all of the data for
192                  * this message, but we can do reassembly on it.
193                  *
194                  * Tell the TCP dissector where the data for this
195                  * message starts in the data it handed us, and
196                  * how many more bytes we need, and return.
197                  */
198                 pinfo->desegment_offset = offset;
199                 pinfo->desegment_len = FCIP_ENCAP_HEADER_LEN;
200                 return -2;
201             }
202         }
203
204         /* I check that we have a valid header before checking for the frame
205          * length and the other initial tests.
206          */
207
208         /*
209          * Tests a, b and c
210          */
211         if (tvb_memeql(tvb, offset, fcip_header_8_bytes, 8) != 0) {
212             offset++;
213             bytes_remaining--;
214             goto NXT_BYTE;
215         }
216
217         flen = (tvb_get_ntohs (tvb, offset+12)) & 0x03FF;
218         frame_len = (tvb_get_ntohs (tvb, offset+12) & 0x03FF)*4;
219
220         if ((flen < 15) || (flen > 545)) {
221             /* Frame length check failed. Skip byte and try again */
222             offset++;
223             bytes_remaining--;
224             goto NXT_BYTE;
225         }
226
227         flen1 = (tvb_get_ntohs (tvb, offset+14)) & 0x03FF;
228
229         if ((flen & 0x03FF) != ((~flen1)&0x03FF)) {
230             /* frame_len and its one's complement are not the same */
231             offset++;
232             bytes_remaining--;
233             goto NXT_BYTE;
234         }
235
236         /* Valid EOF check */
237         if (tvb_bytes_exist (tvb, offset+(frame_len-1)*4, 4)) {
238             eof = (fcip_eof_t)tvb_get_guint8 (tvb, offset+(frame_len-1)*4);
239             eofc = (fcip_eof_t)tvb_get_guint8 (tvb, offset+(frame_len-1)*4+2);
240
241             if ((eof != FCIP_EOFn) && (eof != FCIP_EOFt) && (eof != FCIP_EOFrt)
242                 && (eof != FCIP_EOFdt) && (eof != FCIP_EOFni) &&
243                 (eof != FCIP_EOFdti) && (eof != FCIP_EOFrti) &&
244                 (eof != FCIP_EOFa)) {
245                 offset++;
246                 bytes_remaining--;
247                 goto NXT_BYTE;
248             }
249
250             if ((eof != ~eofc) ||
251                 (eof != tvb_get_guint8 (tvb, offset+(frame_len-1)*4+1)) ||
252                 (eofc != tvb_get_guint8 (tvb, offset+(frame_len-1)*4+3))) {
253                 offset++;
254                 bytes_remaining--;
255                 goto NXT_BYTE;
256             }
257         }
258
259         /* Test d */
260         if ((tvb_get_guint8 (tvb, offset+9) != 0) ||
261             (tvb_get_guint8 (tvb, offset+11) != 0xFF)) {
262             /* Failed */
263             offset++;
264             bytes_remaining--;
265             goto NXT_BYTE;
266         }
267
268         /* Test e */
269
270
271         /* Test f
272          * We dont test this since some implementations actually provide
273          * a CRC here.
274          */
275
276         if (bytes_remaining >= (frame_len)) {
277             if (tvb_bytes_exist (tvb, offset+frame_len, 8)) {
278                 /* The start of the next header matches what we wish to see */
279                 if (tvb_memeql (tvb, offset+frame_len, fcip_header_8_bytes,
280                                 8) == 0) {
281                     return (offset);
282                 }
283                 else {
284                     offset++;
285                     bytes_remaining--;
286                     goto NXT_BYTE;
287                 }
288             }
289             else {
290                 return (offset);
291             }
292         }
293         else {
294             if(fcip_desegment && pinfo->can_desegment) {
295                 /*
296                  * This frame doesn't have all of the data for
297                  * this message, but we can do reassembly on it.
298                  *
299                  * Tell the TCP dissector where the data for this
300                  * message starts in the data it handed us, and
301                  * how many more bytes we need, and return.
302                  */
303                 pinfo->desegment_offset = offset;
304                 pinfo->desegment_len = frame_len - bytes_remaining;
305                 return -2;
306             }
307             else {
308                 return (offset);
309             }
310         }
311     }
312
313     return (-1);                /* Unable to find FCIP header */
314 }
315
316 static void
317 dissect_fcencap_header (tvbuff_t *tvb, proto_tree *tree, gint offset)
318 {
319     guint8 protocol = tvb_get_guint8 (tvb, offset);
320
321     if (tree) {
322         proto_tree_add_uint (tree, hf_fcip_protocol, tvb, offset, 1, protocol);
323         proto_tree_add_item (tree, hf_fcip_version, tvb, offset+1, 1, 0);
324         proto_tree_add_item (tree, hf_fcip_protocol_c, tvb, offset+2, 1, 0);
325         proto_tree_add_item (tree, hf_fcip_version_c, tvb, offset+3, 1, 0);
326
327         if (protocol == FCENCAP_PROTO_FCIP) {
328             proto_tree_add_item (tree, hf_fcip_encap_word1, tvb, offset+4,
329                                  4, 0);
330             proto_tree_add_item (tree, hf_fcip_pflags_changed, tvb, offset+8,
331                                  1, 0);
332             proto_tree_add_item (tree, hf_fcip_pflags_special, tvb, offset+8,
333                                  1, 0);
334             proto_tree_add_item (tree, hf_fcip_pflags_c, tvb, offset+10, 1, 0);
335         }
336
337         /* XXX - break out CRCV flag. */
338         proto_tree_add_item (tree, hf_fcip_flags, tvb, offset+12, 1, 0);
339         proto_tree_add_item (tree, hf_fcip_framelen, tvb, offset+12, 2, 0);
340         proto_tree_add_item (tree, hf_fcip_flags_c, tvb, offset+14, 1, 0);
341         proto_tree_add_item (tree, hf_fcip_framelen_c, tvb, offset+14, 2, 0);
342         proto_tree_add_item (tree, hf_fcip_tsec, tvb, offset+16, 4, 0);
343         proto_tree_add_item (tree, hf_fcip_tusec, tvb, offset+20, 4, 0);
344         /* XXX - check CRC if CRCV is set? */
345         proto_tree_add_item (tree, hf_fcip_encap_crc, tvb, offset+24, 4, 0);
346     }
347 }
348
349 static void
350 dissect_fcip_sf (tvbuff_t *tvb, proto_tree *tree, gint offset)
351 {
352     if (tree) {
353         proto_tree_add_string (tree, hf_fcip_src_wwn, tvb, offset, 8,
354                                fcwwn_to_str (tvb_get_ptr (tvb, offset, 8)));
355         proto_tree_add_item (tree, hf_fcip_src_entity_id, tvb, offset+8, 8,
356                               ENC_NA);
357         proto_tree_add_item (tree, hf_fcip_conn_nonce, tvb, offset+16, 8,
358                               ENC_NA);
359         /* XXX - break out these flags */
360         proto_tree_add_item (tree, hf_fcip_conn_flags, tvb, offset+24, 1, 0);
361         proto_tree_add_item (tree, hf_fcip_conn_code, tvb, offset+26, 2, 0);
362         proto_tree_add_string (tree, hf_fcip_dst_wwn, tvb, offset+30, 8,
363                                fcwwn_to_str (tvb_get_ptr (tvb, offset+30, 8)));
364         proto_tree_add_item (tree, hf_fcip_katov, tvb, offset+38, 4, 0);
365     }
366 }
367
368 static gboolean
369 dissect_fcip (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
370               gboolean check_port)
371 {
372     gint offset = 0,
373          start  = 0,
374          frame_len = 0;
375     gint bytes_remaining = tvb_length (tvb);
376     guint8 pflags, sof = 0, eof = 0;
377    /* Set up structures needed to add the protocol subtree and manage it */
378     proto_item *ti;
379     proto_tree *fcip_tree = NULL;
380     tvbuff_t *next_tvb;
381
382     if (bytes_remaining < FCIP_ENCAP_HEADER_LEN) {
383         return FALSE;
384     }
385
386     if (check_port &&
387         ((pinfo->srcport != fcip_port) && (pinfo->destport != fcip_port))) {
388         return FALSE;
389     }
390
391     while (bytes_remaining > FCIP_ENCAP_HEADER_LEN) {
392         if ((offset = get_next_fcip_header_offset (tvb, pinfo, offset)) == -1) {
393             return FALSE;
394         }
395         else if (offset == -2) {
396             /* We need more data to desegment */
397             return (TRUE);
398         }
399
400         start = offset;
401         col_set_str(pinfo->cinfo, COL_PROTOCOL, "FCIP");
402
403         frame_len = (tvb_get_ntohs (tvb, offset+12) & 0x03FF)*4;
404
405         if (bytes_remaining < frame_len) {
406             if(fcip_desegment && pinfo->can_desegment) {
407                 /*
408                  * This frame doesn't have all of the data for
409                  * this message, but we can do reassembly on it.
410                  *
411                  * Tell the TCP dissector where the data for this
412                  * message starts in the data it handed us, and
413                  * how many more bytes we need, and return.
414                  */
415                 pinfo->desegment_offset = offset;
416                 pinfo->desegment_len = frame_len - bytes_remaining;
417                 return (TRUE);
418             }
419         }
420
421         pflags = tvb_get_guint8 (tvb, start+8);
422
423         if (tree) {
424             if (FCIP_IS_SF (pflags)) {
425                 ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0,
426                                                      FCIP_ENCAP_HEADER_LEN,
427                                                      "FCIP");
428             }
429             else if (tvb_bytes_exist (tvb, offset, offset+frame_len-4)) {
430                 sof = tvb_get_guint8 (tvb, offset+FCIP_ENCAP_HEADER_LEN);
431                 eof = tvb_get_guint8 (tvb, offset+frame_len - 4);
432
433                 ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0,
434                                                      FCIP_ENCAP_HEADER_LEN,
435                                                      "FCIP (%s/%s)",
436                                                      val_to_str (sof, fcip_sof_vals,
437                                                                  "0x%x"),
438                                                      val_to_str (eof, fcip_eof_vals,
439                                                                  "0x%x"));
440             }
441             else {
442                 sof = tvb_get_guint8 (tvb, offset+FCIP_ENCAP_HEADER_LEN);
443
444                 ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0,
445                                                      FCIP_ENCAP_HEADER_LEN,
446                                                      "FCIP (%s/%s)",
447                                                      val_to_str (sof, fcip_sof_vals,
448                                                                  "0x%x"),
449                                                      "NA");
450             }
451             fcip_tree = proto_item_add_subtree (ti, ett_fcip);
452             /* Dissect the Common FC Encap header */
453             dissect_fcencap_header (tvb, fcip_tree, offset);
454
455             offset += FCIP_ENCAP_HEADER_LEN;
456
457             if (!FCIP_IS_SF (pflags)) {
458                 /* print SOF */
459                 proto_tree_add_item (fcip_tree, hf_fcip_sof, tvb, offset, 1, 0);
460                 proto_tree_add_item (fcip_tree, hf_fcip_sof_c, tvb, offset+2, 1, 0);
461                 /* print EOF */
462
463                 offset += (frame_len-FCIP_ENCAP_HEADER_LEN-4);
464                 if (tvb_bytes_exist (tvb, offset, 4)) {
465                     proto_tree_add_item (fcip_tree, hf_fcip_eof, tvb, offset, 1, 0);
466                     proto_tree_add_item (fcip_tree, hf_fcip_eof_c, tvb, offset+2, 1, 0);
467                 }
468             }
469         }
470
471         /* Call the FC Dissector if this is carrying an FC frame */
472         if (!FCIP_IS_SF(pflags)) {
473             /* Set the SOF/EOF flags in the packet_info header */
474             pinfo->sof_eof = 0;
475
476             if (sof) {
477                 if ((sof == FCIP_SOFi3) || (sof == FCIP_SOFi2) || (sof == FCIP_SOFi4)) {
478                     pinfo->sof_eof = PINFO_SOF_FIRST_FRAME;
479                 }
480                 else if (sof == FCIP_SOFf) {
481                     pinfo->sof_eof = PINFO_SOF_SOFF;
482                 }
483
484                 if (eof != FCIP_EOFn) {
485                     pinfo->sof_eof |= PINFO_EOF_LAST_FRAME;
486                 }
487                 else if (eof != FCIP_EOFt) {
488                     pinfo->sof_eof |= PINFO_EOF_INVALID;
489                 }
490             }
491
492             /* Special frame bit is not set */
493             next_tvb = tvb_new_subset_remaining (tvb, FCIP_ENCAP_HEADER_LEN+4);
494             if (fc_handle) {
495                 call_dissector (fc_handle, next_tvb, pinfo, tree);
496             }
497             else if (data_handle) {
498                 call_dissector (data_handle, next_tvb, pinfo, tree);
499             }
500         }
501         else {
502             col_set_str(pinfo->cinfo, COL_INFO, "Special Frame");
503             if (FCIP_IS_CH (pflags)) {
504                 col_append_str(pinfo->cinfo, COL_INFO, "(Changed)");
505             }
506
507             dissect_fcip_sf (tvb, fcip_tree, offset+4);
508         }
509
510         bytes_remaining -= frame_len;
511     }
512
513     return (TRUE);
514 }
515
516 /* This is called for those sessions where we have explicitely said
517    this to be FCIP using "Decode As..."
518    In this case we will not check the port number for sanity and just
519    do as the user said.
520 */
521 static void
522 dissect_fcip_handle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
523 {
524     dissect_fcip (tvb, pinfo, tree, FALSE);
525 }
526
527 static gboolean
528 dissect_fcip_heur (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
529 {
530     return (dissect_fcip (tvb, pinfo, tree, TRUE));
531 }
532
533 void
534 proto_register_fcip (void)
535 {
536
537     /* Setup list of header fields  See Section 1.6.1 for details*/
538     static hf_register_info hf[] = {
539         { &hf_fcip_protocol,
540           { "Protocol", "fcip.proto", FT_UINT8, BASE_DEC,
541             VALS(fcencap_proto_vals), 0, NULL, HFILL }},
542         { &hf_fcip_protocol_c,
543           {"Protocol (1's Complement)", "fcip.protoc", FT_UINT8, BASE_DEC,
544            NULL, 0, NULL, HFILL}},
545         { &hf_fcip_version,
546           {"Version", "fcip.version", FT_UINT8, BASE_DEC,
547            NULL, 0, NULL, HFILL}},
548         { &hf_fcip_version_c,
549           {"Version (1's Complement)", "fcip.versionc", FT_UINT8, BASE_DEC,
550            NULL, 0, NULL, HFILL}},
551         { &hf_fcip_encap_word1,
552           {"FCIP Encapsulation Word1", "fcip.encap_word1", FT_UINT32, BASE_HEX,
553            NULL, 0, NULL, HFILL}},
554         { &hf_fcip_flags,
555           {"Flags", "fcip.flags", FT_UINT8, BASE_HEX,
556            NULL, 0xFC, NULL, HFILL}},
557         { &hf_fcip_flags_c,
558           {"Flags (1's Complement)", "fcip.flagsc", FT_UINT8, BASE_HEX,
559            NULL, 0xFC, NULL, HFILL}},
560         { &hf_fcip_framelen,
561           {"Frame Length (in Words)", "fcip.framelen", FT_UINT16, BASE_DEC,
562            NULL, 0x03FF, NULL, HFILL}},
563         { &hf_fcip_framelen_c,
564           {"Frame Length (1's Complement)", "fcip.framelenc", FT_UINT16, BASE_DEC,
565            NULL, 0x03FF, NULL, HFILL}},
566         { &hf_fcip_tsec,
567           {"Time (secs)", "fcip.tsec", FT_UINT32, BASE_DEC,
568            NULL, 0, NULL, HFILL}},
569         { &hf_fcip_tusec,
570           {"Time (fraction)", "fcip.tusec", FT_UINT32, BASE_DEC,
571            NULL, 0, NULL, HFILL}},
572         { &hf_fcip_encap_crc,
573           {"CRC", "fcip.encap_crc", FT_UINT32, BASE_HEX,
574            NULL, 0, NULL, HFILL}},
575         { &hf_fcip_sof,
576           {"SOF", "fcip.sof", FT_UINT8, BASE_HEX,
577            VALS (&fcip_sof_vals), 0, NULL, HFILL}},
578         { &hf_fcip_sof_c,
579           {"SOF (1's Complement)", "fcip.sofc", FT_UINT8, BASE_HEX,
580            NULL, 0, NULL, HFILL}},
581         { &hf_fcip_eof,
582           {"EOF", "fcip.eof", FT_UINT8, BASE_HEX,
583            VALS (&fcip_eof_vals), 0, NULL, HFILL}},
584         { &hf_fcip_eof_c,
585           {"EOF (1's Complement)", "fcip.eofc", FT_UINT8, BASE_HEX,
586            NULL, 0, NULL, HFILL}},
587         { &hf_fcip_pflags_changed,
588           {"Changed Flag", "fcip.pflags.ch", FT_BOOLEAN, 8,
589            NULL, 0x80, NULL, HFILL}},
590         { &hf_fcip_pflags_special,
591           {"Special Frame Flag", "fcip.pflags.sf", FT_BOOLEAN, 8,
592            NULL, 0x1, NULL, HFILL}},
593         { &hf_fcip_pflags_c,
594           {"Pflags (1's Complement)", "fcip.pflagsc", FT_UINT8, BASE_HEX,
595            NULL, 0x0, NULL, HFILL}},
596         { &hf_fcip_src_wwn,
597           {"Source Fabric WWN", "fcip.srcwwn", FT_STRING, BASE_NONE,
598            NULL, 0x0, NULL, HFILL}},
599         { &hf_fcip_dst_wwn,
600           {"Destination Fabric WWN", "fcip.dstwwn", FT_STRING, BASE_NONE,
601            NULL, 0x0, NULL, HFILL}},
602         { &hf_fcip_src_entity_id,
603           {"FC/FCIP Entity Id", "fcip.srcid", FT_BYTES, BASE_NONE,
604            NULL, 0x0, NULL, HFILL}},
605         { &hf_fcip_conn_flags,
606           {"Connection Usage Flags", "fcip.connflags", FT_UINT8, BASE_HEX,
607            NULL, 0x0, NULL, HFILL}},
608         { &hf_fcip_conn_code,
609           {"Connection Usage Code", "fcip.conncode", FT_UINT16, BASE_HEX,
610            NULL, 0x0, NULL, HFILL}},
611         { &hf_fcip_katov,
612           {"K_A_TOV", "fcip.katov", FT_UINT32, BASE_DEC,
613            NULL, 0x0, NULL, HFILL}},
614         { &hf_fcip_conn_nonce,
615           {"Connection Nonce", "fcip.nonce", FT_BYTES, BASE_NONE,
616            NULL, 0x0, NULL, HFILL}},
617     };
618
619     static gint *ett[] = {
620         &ett_fcip,
621     };
622
623     module_t *fcip_module;
624
625     /* Register the protocol name and description */
626     proto_fcip = proto_register_protocol("FCIP", "Fibre Channel over IP", "fcip");
627
628     /* Required function calls to register the header fields and
629      * subtrees used */
630     proto_register_field_array(proto_fcip, hf, array_length(hf));
631     proto_register_subtree_array(ett, array_length(ett));
632
633     fcip_module = prefs_register_protocol(proto_fcip, NULL);
634     prefs_register_bool_preference(fcip_module,
635                                    "desegment",
636                                    "Reassemble FCIP messages spanning multiple TCP segments",
637                                    "Whether the FCIP dissector should reassemble messages spanning multiple TCP segments."
638                                    " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
639                                    &fcip_desegment);
640     prefs_register_uint_preference(fcip_module,
641                                    "target_port",
642                                    "Target port",
643                                    "Port number used for FCIP",
644                                    10,
645                                    &fcip_port);
646 }
647
648
649 /*
650  * If this dissector uses sub-dissector registration add a
651  * registration routine.
652  */
653
654 /*
655  * This format is required because a script is used to find these
656  * routines and create the code that calls these routines.
657  */
658 void
659 proto_reg_handoff_fcip (void)
660 {
661     dissector_handle_t fcip_handle;
662
663     heur_dissector_add("tcp", dissect_fcip_heur, proto_fcip);
664
665     fcip_handle = create_dissector_handle(dissect_fcip_handle, proto_fcip);
666     dissector_add_handle("tcp.port", fcip_handle);
667
668     data_handle = find_dissector("data");
669     fc_handle = find_dissector("fc");
670 }