Coverage Report

Created: 2025-08-04 07:15

/src/wireshark/epan/dissectors/packet-ifcp.c
Line
Count
Source (jump to first uncovered line)
1
/* packet-ifcp.c
2
 * Routines for iFCP dissection
3
 * RFC 3821, RFC 3643
4
 *
5
 * Copyright 2005   Aboo Valappil     (valappil_aboo@emc.com)
6
 *           2006 ronnie sahlberg   major refactoring
7
 *
8
 *
9
 * Significantly based on packet-fcip.c by
10
 *       Copyright 2001, Dinesh G Dutt (ddutt@cisco.com)
11
 *
12
 * Wireshark - Network traffic analyzer
13
 * By Gerald Combs <gerald@wireshark.org>
14
 * Copyright 1998 Gerald Combs
15
 *
16
 * SPDX-License-Identifier: GPL-2.0-or-later
17
 */
18
19
#include "config.h"
20
21
#include <epan/packet.h>
22
#include <epan/prefs.h>
23
#include <epan/tfs.h>
24
#include <wsutil/array.h>
25
26
#include "packet-tcp.h"
27
#include "packet-fc.h"
28
29
void proto_register_ifcp(void);
30
void proto_reg_handoff_ifcp(void);
31
32
0
#define iFCP_ENCAP_HEADER_LEN     28
33
2.73k
#define iFCP_MIN_HEADER_LEN       16 /* up to frame len field */
34
35
typedef enum {
36
    iFCP_EOFn    = 0x41,
37
    iFCP_EOFt    = 0x42,
38
    iFCP_EOFrt   = 0x44,
39
    iFCP_EOFdt   = 0x46,
40
    iFCP_EOFni   = 0x49,
41
    iFCP_EOFdti  = 0x4E,
42
    iFCP_EOFrti  = 0x4F,
43
    iFCP_EOFa    = 0x50
44
} ifcp_eof_t;
45
46
typedef enum {
47
    iFCP_SOFf    = 0x28,
48
    iFCP_SOFi4   = 0x29,
49
    iFCP_SOFi2   = 0x2D,
50
    iFCP_SOFi3   = 0x2E,
51
    iFCP_SOFn4   = 0x31,
52
    iFCP_SOFn2   = 0x35,
53
    iFCP_SOFn3   = 0x36,
54
    iFCP_SOFc4   = 0x39
55
} ifcp_sof_t;
56
57
typedef enum {
58
    FCENCAP_PROTO_FCIP = 1,
59
    FCENCAP_PROTO_iFCP = 2
60
} fcencap_proto_t;
61
62
static const value_string ifcp_eof_vals[] = {
63
    {iFCP_EOFn,   "EOFn" },
64
    {iFCP_EOFt,   "EOFt" },
65
    {iFCP_EOFrt,  "EOFrt" },
66
    {iFCP_EOFdt,  "EOFdt" },
67
    {iFCP_EOFni,  "EOFni" },
68
    {iFCP_EOFdti, "EOFdti" },
69
    {iFCP_EOFrti, "EOFrti" },
70
    {iFCP_EOFa,   "EOFa" },
71
    {0, NULL},
72
};
73
74
static const value_string ifcp_sof_vals[] = {
75
    {iFCP_SOFf,  "SOFf" },
76
    {iFCP_SOFi4, "SOFi4" },
77
    {iFCP_SOFi2, "SOFi2" },
78
    {iFCP_SOFi3, "SOFi3" },
79
    {iFCP_SOFn4, "SOFn4" },
80
    {iFCP_SOFn2, "SOFn2" },
81
    {iFCP_SOFn3, "SOFn3" },
82
    {iFCP_SOFc4, "SOFc4" },
83
    {0, NULL},
84
};
85
86
static const value_string fcencap_proto_vals[] = {
87
    {FCENCAP_PROTO_FCIP, "FCIP"},
88
    {FCENCAP_PROTO_iFCP, "iFCP"},
89
    {0, NULL},
90
};
91
92
/* RFC 4172 section 5.3.1 shows a chart of the iFCP encapsulated Header Format.
93
 * It says that bytes 4-7 MUST be zeros.  In reality most vendors are putting
94
 * some information in these 4 bytes, particularly Nishon.
95
 */
96
static const uint8_t ifcp_header_4_bytes[4] = {
97
    0x02, 0x01, 0xFD, 0xFE
98
};
99
100
static int proto_ifcp;
101
102
static int hf_ifcp_protocol;
103
static int hf_ifcp_protocol_c;
104
static int hf_ifcp_version;
105
static int hf_ifcp_version_c;
106
static int hf_ifcp_encap_flags_c;
107
static int hf_ifcp_framelen;
108
static int hf_ifcp_framelen_c;
109
static int hf_ifcp_tsec;
110
static int hf_ifcp_tusec;
111
static int hf_ifcp_encap_crc;
112
static int hf_ifcp_sof;
113
static int hf_ifcp_sof_c;
114
static int hf_ifcp_eof;
115
static int hf_ifcp_eof_c;
116
static int hf_ifcp_ls_command_acc;
117
static int hf_ifcp_flags;
118
static int hf_ifcp_flags_ses;
119
static int hf_ifcp_flags_trp;
120
static int hf_ifcp_flags_spc;
121
static int hf_ifcp_common_flags;
122
static int hf_ifcp_common_flags_crcv;
123
124
static int ett_ifcp;
125
static int ett_ifcp_sof;
126
static int ett_ifcp_eof;
127
static int ett_ifcp_flags;
128
static int ett_ifcp_common_flags;
129
static int ett_ifcp_protocol;
130
static int ett_ifcp_version;
131
static int ett_ifcp_frame_len;
132
133
static bool ifcp_desegment    = true;
134
135
static dissector_handle_t ifcp_handle;
136
static dissector_handle_t fc_handle;
137
138
139
/* This function checks the first 16 bytes of the "header" that it looks sane
140
 * and returns true if this looks like iFCP and false if it doesn't.
141
 */
142
static bool
143
ifcp_header_test(tvbuff_t *tvb, int offset)
144
2.73k
{
145
2.73k
    uint16_t flen, flen1;
146
147
    /* we can only do this test if we have 16 bytes or more */
148
2.73k
    if(tvb_captured_length_remaining(tvb, offset)<iFCP_MIN_HEADER_LEN){
149
763
        return false;
150
763
    }
151
152
    /*
153
    * As per the iFCP standard, the following tests must PASS:
154
    * 1)  Frame Length field validation -- 15 < Frame Length < 545;
155
    * 2)  Comparison of Frame Length field to its ones complement; and
156
    * 3)  A valid EOF is found in the word preceding the start of the next
157
    *     iFCP header as indicated by the Frame Length field, to be tested
158
    *     as follows:
159
    *     1)  Bits 24-31 and 16-23 contain identical legal EOF values (the
160
    *         list of legal EOF values is in the FC Frame Encapsulation
161
    *         [21]); and
162
    *     2)  Bits 8-15 and 0-7 contain the ones complement of the EOF
163
    *         value found in bits 24-31.
164
    *
165
    * As per the iFCP standard, in addition, at least 3 of the following
166
    * set of tests must be performed to identify that we've located the
167
    * start of an iFCP frame.
168
    * a)  Protocol# ones complement field (1 test);
169
    * b)  Version ones complement field (1 test);
170
    * c)  Replication of encapsulation word 0 in word 1 (1 test);
171
    * d)  Reserved field and its ones complement (2 tests);
172
    * e)  Flags field and its ones complement (2 tests);
173
    *    f)  CRC field is equal to zero (1 test); (DON'T DO THIS TEST!)
174
    * g)  SOF fields and ones complement fields (4 tests);
175
    * h)  Format and values of FC header (1 test);
176
    * i)  CRC of FC Frame (2 tests);
177
    * j)  FC Frame Encapsulation header information in the next iFCP Frame
178
    *     (1 test).
179
    *
180
    * At least 3 of the 16 tests listed above SHALL be performed. Failure
181
    * of any of the above tests actually performed SHALL indicate an
182
    * encapsulation error and the FC Frame SHALL NOT be forwarded on to
183
    * the FC Entity.
184
    */
185
186
187
    /*
188
     * Tests a, b and c
189
     */
190
1.97k
    if(tvb_memeql(tvb, offset, ifcp_header_4_bytes, 4) != 0){
191
1.96k
        return false;
192
1.96k
        }
193
194
    /* check the frame length */
195
7
    flen=tvb_get_ntohs(tvb, offset+12)&0x03FF;
196
7
    if((flen < 15) || (flen > 545)){
197
4
        return false;
198
4
    }
199
200
    /* check the complement of the frame length */
201
3
    flen1=tvb_get_ntohs(tvb, offset+14)&0x03FF;
202
3
    if(flen!=((~flen1)&0x03FF)){
203
3
        return false;
204
3
    }
205
206
207
    /* this should be good enough for our heuristics */
208
0
    return true;
209
3
}
210
211
212
14
#define IFCP_FLAGS_SES      0x04
213
14
#define IFCP_FLAGS_TRP      0x02
214
14
#define IFCP_FLAGS_SPC      0x01
215
216
static const true_false_string ifcp_flags_ses_tfs = {
217
    "This is a SESSION CONTROL FRAME",
218
    "This is a normal frame"
219
};
220
221
static const true_false_string ifcp_flags_trp_tfs = {
222
    "Address TRANSPARENT Mode Enabled",
223
    "Address TRANSLATION Mode Enabled"
224
};
225
226
static const true_false_string ifcp_flags_spc_tfs = {
227
    "This frame requires SPECIAL PROCESSING",
228
    "This is a normal frame"
229
};
230
231
static int
232
dissect_ifcpflags(tvbuff_t *tvb, int offset, proto_tree *parent_tree)
233
0
{
234
0
    static int * const flags[] = {
235
0
        &hf_ifcp_flags_ses,
236
0
        &hf_ifcp_flags_trp,
237
0
        &hf_ifcp_flags_spc,
238
0
        NULL
239
0
    };
240
0
    proto_tree_add_bitmask(parent_tree, tvb, offset, hf_ifcp_flags,
241
0
                           ett_ifcp_flags, flags, ENC_BIG_ENDIAN);
242
243
0
    offset++;
244
0
    return offset;
245
0
}
246
247
248
14
#define IFCP_COMMON_FLAGS_CRCV      0x04
249
250
static void
251
dissect_commonflags(tvbuff_t *tvb, int offset, proto_tree *parent_tree)
252
0
{
253
0
    static int * const flags[] = {
254
0
        &hf_ifcp_common_flags_crcv,
255
0
        NULL
256
0
    };
257
258
0
    proto_tree_add_bitmask(parent_tree, tvb, offset, hf_ifcp_common_flags,
259
0
                           ett_ifcp_common_flags, flags, ENC_BIG_ENDIAN);
260
0
}
261
262
static int
263
dissect_ifcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data _U_)
264
0
{
265
0
    int         offset = 0, frame_len = 0;
266
0
    uint8_t     sof    = 0, eof = 0;
267
0
    proto_item *ti;
268
0
    proto_tree *tree           = NULL;
269
0
    tvbuff_t   *next_tvb;
270
0
    uint8_t     protocol;
271
0
    proto_tree *protocol_tree  = NULL;
272
0
    proto_tree *version_tree   = NULL;
273
0
    proto_tree *frame_len_tree = NULL;
274
0
    proto_tree *sof_tree       = NULL;
275
0
    proto_tree *eof_tree       = NULL;
276
0
    fc_data_t   fc_data;
277
278
    /* verify we have a full header  (do we need to do this? */
279
0
    if(tvb_captured_length(tvb)<iFCP_ENCAP_HEADER_LEN){
280
0
        return 0;
281
0
    }
282
283
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "iFCP");
284
285
0
    frame_len = (tvb_get_ntohs (tvb, offset+12) & 0x03FF)*4;
286
287
288
0
        if (parent_tree) {
289
0
            if (tvb_bytes_exist (tvb, offset, frame_len-4)) {
290
0
                sof = tvb_get_uint8 (tvb, offset+iFCP_ENCAP_HEADER_LEN);
291
0
                eof = tvb_get_uint8 (tvb, offset+frame_len - 4);
292
293
0
                ti = proto_tree_add_protocol_format (parent_tree, proto_ifcp, tvb, offset,
294
0
                                                     iFCP_ENCAP_HEADER_LEN,
295
0
                                                     "iFCP (%s/%s)",
296
0
                                                     val_to_str (sof, ifcp_sof_vals,
297
0
                                                                 "0x%x"),
298
0
                                                     val_to_str (eof, ifcp_eof_vals,
299
0
                                                                 "0x%x"));
300
0
            } else {
301
0
                sof = tvb_get_uint8 (tvb, offset+iFCP_ENCAP_HEADER_LEN);
302
303
0
                ti = proto_tree_add_protocol_format (parent_tree, proto_ifcp, tvb, offset,
304
0
                                                     iFCP_ENCAP_HEADER_LEN,
305
0
                                                     "iFCP (%s/%s)",
306
0
                                                     val_to_str (sof, ifcp_sof_vals,
307
0
                                                                 "0x%x"),
308
0
                                                     "NA");
309
0
            }
310
0
            tree = proto_item_add_subtree (ti, ett_ifcp);
311
0
        }
312
313
314
315
    /* The Common FC Encap header */
316
    /* protocol */
317
0
    protocol = tvb_get_uint8 (tvb, offset);
318
0
    ti=proto_tree_add_item(tree, hf_ifcp_protocol, tvb, offset, 1, ENC_BIG_ENDIAN);
319
0
    protocol_tree=proto_item_add_subtree(ti, ett_ifcp_protocol);
320
321
0
    offset++;
322
323
    /* version */
324
0
    ti=proto_tree_add_item(tree, hf_ifcp_version, tvb, offset, 1, ENC_BIG_ENDIAN);
325
0
    version_tree=proto_item_add_subtree(ti, ett_ifcp_version);
326
0
    offset++;
327
328
    /* protocol complement */
329
0
    proto_tree_add_item(protocol_tree, hf_ifcp_protocol_c, tvb, offset, 1, ENC_BIG_ENDIAN);
330
0
    offset++;
331
332
    /* version complement */
333
0
    proto_tree_add_item(version_tree, hf_ifcp_version_c, tvb, offset, 1, ENC_BIG_ENDIAN);
334
0
    offset++;
335
336
    /* 4 reserved bytes */
337
0
    offset+=4;
338
339
    /* iFCP specific fields */
340
0
    if(protocol==FCENCAP_PROTO_iFCP){
341
        /* LS_COMMAND_ACC */
342
0
        proto_tree_add_item(tree, hf_ifcp_ls_command_acc, tvb, offset, 1, ENC_BIG_ENDIAN);
343
0
        offset++;
344
345
        /* iFCP Flags */
346
0
        offset=dissect_ifcpflags(tvb, offset, tree);
347
348
        /* SOF */
349
0
        ti=proto_tree_add_item(tree, hf_ifcp_sof, tvb, offset, 1, ENC_BIG_ENDIAN);
350
0
        sof_tree=proto_item_add_subtree(ti, ett_ifcp_sof);
351
0
        offset++;
352
353
        /* EOF */
354
0
        ti=proto_tree_add_item(tree, hf_ifcp_eof, tvb, offset, 1, ENC_BIG_ENDIAN);
355
0
        eof_tree=proto_item_add_subtree(ti, ett_ifcp_eof);
356
0
        offset++;
357
0
    } else {
358
0
        offset+=4;
359
0
        sof_tree=tree; /* better than nothing */
360
0
        eof_tree=tree;
361
0
    }
362
363
    /* Common Flags */
364
0
    dissect_commonflags(tvb, offset, tree);
365
366
    /* frame len */
367
0
    ti=proto_tree_add_item(tree, hf_ifcp_framelen, tvb, offset, 2, ENC_BIG_ENDIAN);
368
0
    frame_len_tree=proto_item_add_subtree(ti, ett_ifcp_frame_len);
369
0
    offset+=2;
370
371
    /* complement of flags and frame len */
372
0
    proto_tree_add_item(frame_len_tree, hf_ifcp_encap_flags_c, tvb, offset, 1, ENC_BIG_ENDIAN);
373
0
    proto_tree_add_item(frame_len_tree, hf_ifcp_framelen_c, tvb, offset, 2, ENC_BIG_ENDIAN);
374
0
    offset+=2;
375
376
    /* timestamp seconds */
377
0
    proto_tree_add_item(tree, hf_ifcp_tsec, tvb, offset, 4, ENC_BIG_ENDIAN);
378
0
    offset+=4;
379
380
    /* timestamp fractions */
381
0
    proto_tree_add_item(tree, hf_ifcp_tusec, tvb, offset, 4, ENC_BIG_ENDIAN);
382
0
    offset+=4;
383
384
    /* crc */
385
0
    proto_tree_add_item(tree, hf_ifcp_encap_crc, tvb, offset, 4, ENC_BIG_ENDIAN);
386
0
    offset+=4;
387
388
389
    /* FC SOF/-SOF */
390
0
    proto_tree_add_item(sof_tree, hf_ifcp_sof, tvb, offset, 1, ENC_BIG_ENDIAN);
391
0
    offset++;
392
0
    proto_tree_add_item(sof_tree, hf_ifcp_sof, tvb, offset, 1, ENC_BIG_ENDIAN);
393
0
    offset++;
394
0
    proto_tree_add_item(sof_tree, hf_ifcp_sof_c, tvb, offset, 1, ENC_BIG_ENDIAN);
395
0
    offset++;
396
0
    proto_tree_add_item(sof_tree, hf_ifcp_sof_c, tvb, offset, 1, ENC_BIG_ENDIAN);
397
0
    offset++;
398
399
    /* FC EOF/-EOF */
400
0
    if(tvb_bytes_exist(tvb, frame_len-4, 4)) {
401
0
        proto_tree_add_item(eof_tree, hf_ifcp_eof, tvb, frame_len-4, 1, ENC_BIG_ENDIAN);
402
0
        proto_tree_add_item(eof_tree, hf_ifcp_eof, tvb, frame_len-3, 1, ENC_BIG_ENDIAN);
403
0
        proto_tree_add_item(eof_tree, hf_ifcp_eof_c, tvb, frame_len-2, 1, ENC_BIG_ENDIAN);
404
0
        proto_tree_add_item(eof_tree, hf_ifcp_eof_c, tvb, frame_len-1, 1, ENC_BIG_ENDIAN);
405
0
        }
406
407
408
    /* Call the FC Dissector if this is carrying an FC frame */
409
    /* Set the SOF/EOF flags in the packet_info header */
410
0
    fc_data.sof_eof = 0;
411
412
0
    switch(sof){
413
0
    case iFCP_SOFi3:
414
0
    case iFCP_SOFi2:
415
0
    case iFCP_SOFi4:
416
0
        fc_data.sof_eof = FC_DATA_SOF_FIRST_FRAME;
417
0
        break;
418
0
    case iFCP_SOFf:
419
0
        fc_data.sof_eof = FC_DATA_SOF_SOFF;
420
0
        break;
421
0
    default:
422
0
        if(sof){
423
0
            if (eof != iFCP_EOFn) {
424
0
                fc_data.sof_eof |= FC_DATA_EOF_LAST_FRAME;
425
0
                    } else if (eof != iFCP_EOFt) {
426
0
                fc_data.sof_eof |= FC_DATA_EOF_INVALID;
427
0
            }
428
0
        }
429
0
    }
430
431
0
    next_tvb=tvb_new_subset_length(tvb, offset, frame_len-offset-4);
432
0
    fc_data.ethertype = ETHERTYPE_UNK;
433
434
0
    if(fc_handle){
435
0
        call_dissector_with_data(fc_handle, next_tvb, pinfo, parent_tree, &fc_data);
436
0
    } else {
437
0
        call_data_dissector(next_tvb, pinfo, parent_tree);
438
0
    }
439
440
0
    return tvb_captured_length(tvb);
441
0
}
442
443
static unsigned
444
get_ifcp_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
445
0
{
446
0
    unsigned pdu_len;
447
448
0
    if(!ifcp_header_test(tvb, offset)){
449
0
        return 0;
450
0
    }
451
452
0
    pdu_len=(tvb_get_ntohs(tvb, offset+12)&0x03FF)*4;
453
0
    return pdu_len;
454
0
}
455
456
static int
457
dissect_ifcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data)
458
0
{
459
0
    tcp_dissect_pdus(tvb, pinfo, parent_tree, ifcp_desegment, iFCP_MIN_HEADER_LEN, get_ifcp_pdu_len, dissect_ifcp_pdu, data);
460
0
    return tvb_captured_length(tvb);
461
0
}
462
463
464
/* This is called for those sessions where we have explicitly said
465
 * this to be iFCP using "Decode As..."
466
 * In this case we will not check the port number for sanity and just
467
 * do as the user said.
468
 */
469
static int
470
dissect_ifcp_handle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
471
0
{
472
0
    return dissect_ifcp(tvb, pinfo, tree, data);
473
0
}
474
475
static bool
476
dissect_ifcp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
477
2.73k
{
478
2.73k
    if(!ifcp_header_test(tvb, 0)){
479
2.73k
        return false;
480
2.73k
    }
481
482
0
    dissect_ifcp(tvb, pinfo, tree, data);
483
484
    /* our heuristics are so strong that if the heuristics above passed
485
     * and the dissection of the pdu did not cause any exceptions
486
     * then we can set this as our conversation dissector
487
     */
488
0
    if(ifcp_handle){
489
0
        conversation_t* ifcp_conv;
490
491
0
        ifcp_conv=find_or_create_conversation(pinfo);
492
        /* XXX why does this not work? it doesn't result in dissect_ifcp_handle being called    look into later*/
493
0
        conversation_set_dissector(ifcp_conv, ifcp_handle);
494
0
    }
495
496
0
    return true;
497
2.73k
}
498
499
void
500
proto_register_ifcp (void)
501
14
{
502
    /* Setup list of header fields  See Section 1.6.1 for details*/
503
14
    static hf_register_info hf[] = {
504
14
        { &hf_ifcp_protocol,
505
14
          {"Protocol", "ifcp.encap.proto", FT_UINT8, BASE_DEC, VALS(fcencap_proto_vals), 0,
506
14
           NULL, HFILL }},
507
14
        { &hf_ifcp_protocol_c,
508
14
          {"Protocol (1's Complement)", "ifcp.encap.protoc", FT_UINT8, BASE_DEC, NULL, 0,
509
14
           NULL, HFILL}},
510
14
        { &hf_ifcp_version,
511
14
          {"Version", "ifcp.encap.version", FT_UINT8, BASE_DEC, NULL, 0,
512
14
           NULL, HFILL}},
513
14
        { &hf_ifcp_version_c,
514
14
          {"Version (1's Complement)", "ifcp.encap.versionc", FT_UINT8, BASE_DEC, NULL, 0,
515
14
           NULL, HFILL}},
516
14
        { &hf_ifcp_encap_flags_c,
517
14
          {"iFCP Encapsulation Flags (1's Complement)", "ifcp.encap_flagsc", FT_UINT8, BASE_HEX, NULL, 0xFC,
518
14
           NULL, HFILL}},
519
14
        { &hf_ifcp_framelen,
520
14
          {"Frame Length (in Words)", "ifcp.encap.framelen", FT_UINT16, BASE_DEC, NULL, 0x03FF,
521
14
           NULL, HFILL}},
522
14
        { &hf_ifcp_framelen_c,
523
14
          {"Frame Length (1's Complement)", "ifcp.encap.framelenc", FT_UINT16, BASE_DEC, NULL, 0x03FF,
524
14
           NULL, HFILL}},
525
14
        { &hf_ifcp_tsec,
526
14
          {"Time (secs)", "ifcp.encap.tsec", FT_UINT32, BASE_DEC, NULL, 0,
527
14
           NULL, HFILL}},
528
14
        { &hf_ifcp_tusec,
529
14
          {"Time (fraction)", "ifcp.encap.tusec", FT_UINT32, BASE_DEC, NULL, 0,
530
14
           NULL, HFILL}},
531
14
        { &hf_ifcp_encap_crc,
532
14
          {"CRC", "ifcp.encap.crc", FT_UINT32, BASE_HEX, NULL, 0,
533
14
           NULL, HFILL}},
534
14
        { &hf_ifcp_sof,
535
14
          {"SOF", "ifcp.sof", FT_UINT8, BASE_HEX, VALS (ifcp_sof_vals), 0,
536
14
           NULL, HFILL}},
537
14
        { &hf_ifcp_eof,
538
14
          {"EOF", "ifcp.eof", FT_UINT8, BASE_HEX, VALS (ifcp_eof_vals), 0,
539
14
           NULL, HFILL}},
540
14
        { &hf_ifcp_sof_c,
541
14
          {"SOF Compliment", "ifcp.sof_c", FT_UINT8, BASE_HEX, NULL , 0,
542
14
           NULL, HFILL}},
543
14
        { &hf_ifcp_eof_c,
544
14
          {"EOF Compliment", "ifcp.eof_c", FT_UINT8, BASE_HEX, NULL , 0,
545
14
           NULL, HFILL}},
546
14
        { &hf_ifcp_ls_command_acc,
547
14
          {"Ls Command Acc", "ifcp.ls_command_acc", FT_UINT8, BASE_HEX, NULL, 0,
548
14
           NULL, HFILL}},
549
14
        { &hf_ifcp_common_flags,
550
14
          {"Flags", "ifcp.common_flags", FT_UINT8, BASE_HEX , NULL, 0xfc,
551
14
           NULL, HFILL }},
552
14
        { &hf_ifcp_common_flags_crcv,
553
14
          {"CRC", "ifcp.common_flags.crcv", FT_BOOLEAN, 8, TFS(&tfs_valid_not_valid), IFCP_COMMON_FLAGS_CRCV,
554
14
           "Is the CRC field valid?", HFILL }},
555
14
        { &hf_ifcp_flags,
556
14
          {"iFCP Flags", "ifcp.flags", FT_UINT8, BASE_HEX , NULL, 0,
557
14
           NULL, HFILL }},
558
14
        { &hf_ifcp_flags_ses,
559
14
          {"SES", "ifcp.flags.ses", FT_BOOLEAN, 8, TFS(&ifcp_flags_ses_tfs), IFCP_FLAGS_SES,
560
14
           "Is this a Session control frame", HFILL }},
561
14
        { &hf_ifcp_flags_trp,
562
14
          {"TRP", "ifcp.flags.trp", FT_BOOLEAN, 8, TFS(&ifcp_flags_trp_tfs), IFCP_FLAGS_TRP,
563
14
           "Is address transparent mode enabled", HFILL }},
564
14
        { &hf_ifcp_flags_spc,
565
14
          {"SPC", "ifcp.flags.spc", FT_BOOLEAN, 8, TFS(&ifcp_flags_spc_tfs), IFCP_FLAGS_SPC,
566
14
           "Is frame part of link service", HFILL }},
567
14
    };
568
569
14
    static int *ett[] = {
570
14
        &ett_ifcp,
571
14
        &ett_ifcp_sof,
572
14
        &ett_ifcp_eof,
573
14
        &ett_ifcp_protocol,
574
14
        &ett_ifcp_version,
575
14
    &ett_ifcp_frame_len,
576
14
        &ett_ifcp_flags,
577
14
        &ett_ifcp_common_flags,
578
14
    };
579
580
14
    module_t *ifcp_module;
581
582
    /* Register the protocol name and description */
583
14
    proto_ifcp = proto_register_protocol("iFCP", "iFCP", "ifcp");
584
585
14
    proto_register_field_array(proto_ifcp, hf, array_length(hf));
586
14
    proto_register_subtree_array(ett, array_length(ett));
587
588
14
    ifcp_module = prefs_register_protocol(proto_ifcp, NULL);
589
14
    prefs_register_bool_preference(ifcp_module,
590
14
                                   "desegment",
591
14
                                   "Reassemble iFCP messages spanning multiple TCP segments",
592
14
                                   "Whether the iFCP dissector should reassemble messages spanning multiple TCP segments."
593
14
                                   " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
594
14
                                   &ifcp_desegment);
595
14
    prefs_register_obsolete_preference(ifcp_module, "target_port");
596
597
14
    ifcp_handle = register_dissector("ifcp", dissect_ifcp_handle, proto_ifcp);
598
14
}
599
600
void
601
proto_reg_handoff_ifcp (void)
602
14
{
603
14
    heur_dissector_add("tcp", dissect_ifcp_heur, "iFCP over TCP", "ifcp_tcp", proto_ifcp, HEURISTIC_ENABLE);
604
605
14
    dissector_add_for_decode_as_with_preference("tcp.port", ifcp_handle);
606
607
14
    fc_handle = find_dissector_add_dependency("fc_ifcp", proto_ifcp);
608
14
}
609
610
/*
611
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
612
 *
613
 * Local variables:
614
 * c-basic-offset: 4
615
 * tab-width: 8
616
 * indent-tabs-mode: nil
617
 * End:
618
 *
619
 * vi: set shiftwidth=4 tabstop=8 expandtab:
620
 * :indentSize=4:tabSize=8:noTabs=true:
621
 */