Coverage Report

Created: 2026-09-28 06:52

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