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-fcfzs.c
Line
Count
Source
1
/* packet-fcfzs.c
2
 * Routines for FC Fabric Zone Server
3
 * Copyright 2001, Dinesh G Dutt <ddutt@andiamo.com>
4
 *
5
 * Wireshark - Network traffic analyzer
6
 * By Gerald Combs <gerald@wireshark.org>
7
 * Copyright 1998 Gerald Combs
8
 *
9
 * SPDX-License-Identifier: GPL-2.0-or-later
10
 */
11
12
/*
13
 * Fibre Channel Generic Services (FC-GS) specification.
14
 */
15
16
#include "config.h"
17
18
#include <epan/packet.h>
19
#include <epan/tfs.h>
20
#include <epan/expert.h>
21
22
#include <wsutil/ws_padding_to.h>
23
24
#include "packet-fc.h"
25
#include "packet-fcct.h"
26
#include "packet-fcfzs.h"
27
28
void proto_register_fcfzs(void);
29
void proto_reg_handoff_fcfzs(void);
30
31
static dissector_handle_t fzs_handle;
32
33
/* Initialize the protocol and registered fields */
34
static int proto_fcfzs;
35
static int hf_fcfzs_opcode;
36
static int hf_fcfzs_gzc_vendor;
37
static int hf_fcfzs_gest_vendor;
38
static int hf_fcfzs_numzoneattrs;
39
static int hf_fcfzs_zonesetnmlen;
40
static int hf_fcfzs_zonesetname;
41
static int hf_fcfzs_numzones;
42
static int hf_fcfzs_numzonesetattrs;
43
static int hf_fcfzs_zonenmlen;
44
static int hf_fcfzs_zonename;
45
static int hf_fcfzs_nummbrs;
46
static int hf_fcfzs_nummbrentries;
47
static int hf_fcfzs_mbrid_fcwwn;
48
static int hf_fcfzs_mbrid_fc;
49
static int hf_fcfzs_mbrid_uint;
50
/* static int hf_fcfzs_mbridlen; */
51
static int hf_fcfzs_mbrtype;
52
static int hf_fcfzs_reason;
53
static int hf_fcfzs_rjtdetail;
54
static int hf_fcfzs_rjtvendor;
55
static int hf_fcfzs_maxres_size;
56
static int hf_fcfzs_mbrid_lun;
57
static int hf_fcfzs_gzc_flags;
58
static int hf_fcfzs_gzc_flags_hard_zones;
59
static int hf_fcfzs_gzc_flags_soft_zones;
60
static int hf_fcfzs_gzc_flags_zoneset_db;
61
static int hf_fcfzs_zone_state;
62
static int hf_fcfzs_soft_zone_set_enforced;
63
static int hf_fcfzs_hard_zone_set_enforced;
64
65
/* Initialize the subtree pointers */
66
static int ett_fcfzs;
67
static int ett_fcfzs_gzc_flags;
68
static int ett_fcfzs_zone_state;
69
70
static expert_field ei_fcfzs_no_exchange;
71
static expert_field ei_fcfzs_mbrid;
72
73
typedef struct _fcfzs_conv_key {
74
    uint32_t conv_idx;
75
} fcfzs_conv_key_t;
76
77
typedef struct _fcfzs_conv_data {
78
    uint32_t opcode;
79
} fcfzs_conv_data_t;
80
81
static wmem_map_t *fcfzs_req_hash;
82
83
/*
84
 * Hash Functions
85
 */
86
static int
87
fcfzs_equal(const void *v, const void *w)
88
42
{
89
42
    const fcfzs_conv_key_t *v1 = (const fcfzs_conv_key_t *)v;
90
42
    const fcfzs_conv_key_t *v2 = (const fcfzs_conv_key_t *)w;
91
92
42
    return (v1->conv_idx == v2->conv_idx);
93
42
}
94
95
static unsigned
96
fcfzs_hash(const void *v)
97
59
{
98
59
    const fcfzs_conv_key_t *key = (const fcfzs_conv_key_t *)v;
99
59
    unsigned val;
100
101
59
    val = key->conv_idx;
102
103
59
    return val;
104
59
}
105
106
/* Code to actually dissect the packets */
107
static void
108
dissect_fcfzs_zoneset(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, unsigned offset)
109
26
{
110
26
    unsigned numzones, nummbrs, i, j;
111
26
    uint32_t len;
112
26
    proto_item* ti;
113
114
    /* The zoneset structure has the following format */
115
    /* zoneset name (len[not including pad], name, pad),
116
     * number of zones,
117
     * for each zone,
118
     *     Zone name (len[not including pad], name, pad), num zone mbrs
119
     *     for each zone mbr,
120
     *         zone mbr id type, zone mbr id (len, name, pad)
121
     */
122
123
        /* Zoneset Name */
124
26
        proto_tree_add_item_ret_uint(tree, hf_fcfzs_zonesetnmlen, tvb, offset,
125
26
                            1, ENC_BIG_ENDIAN, &len);
126
26
        offset += 4;
127
26
        proto_tree_add_item(tree, hf_fcfzs_zonesetname, tvb, offset,
128
26
                            len, ENC_ASCII);
129
26
        offset += len;
130
        /* Fill Bytes */
131
26
        offset += WS_PADDING_TO_4(len);
132
133
134
        /* Number of zones */
135
26
        proto_tree_add_item_ret_uint(tree, hf_fcfzs_numzones, tvb, offset, 4, ENC_BIG_ENDIAN, &numzones);
136
26
        offset += 4;
137
138
        /* For each zone... */
139
96
        for (i = 0; i < numzones; i++) {
140
93
            proto_tree_add_item_ret_uint(tree, hf_fcfzs_zonenmlen, tvb, offset,
141
93
                1, ENC_BIG_ENDIAN, &len);
142
93
            offset += 4;
143
93
            proto_tree_add_item(tree, hf_fcfzs_zonename, tvb, offset,
144
93
                                len, ENC_ASCII);
145
93
            offset += len;
146
            /* Fill Bytes */
147
93
            offset += WS_PADDING_TO_4(len);
148
149
93
            proto_tree_add_item_ret_uint(tree, hf_fcfzs_nummbrentries, tvb, offset,
150
93
                                         4, ENC_BIG_ENDIAN, &nummbrs);
151
152
93
            offset += 4;
153
391
            for (j = 0; j < nummbrs; j++) {
154
321
                uint32_t mbrtype;
155
321
                ti = proto_tree_add_item_ret_uint(tree, hf_fcfzs_mbrtype, tvb, offset, 1, ENC_BIG_ENDIAN, &mbrtype);
156
157
321
                switch (mbrtype) {
158
11
                case FC_FZS_ZONEMBR_PWWN:
159
16
                case FC_FZS_ZONEMBR_NWWN:
160
16
                    proto_tree_add_item(tree, hf_fcfzs_mbrid_fcwwn, tvb,
161
16
                                          offset+4, 8, ENC_NA);
162
16
                    break;
163
10
                case FC_FZS_ZONEMBR_DP:
164
10
                    proto_tree_add_item(tree, hf_fcfzs_mbrid_uint,
165
10
                                                 tvb, offset+4, 3, ENC_BIG_ENDIAN);
166
10
                    break;
167
9
                case FC_FZS_ZONEMBR_FCID:
168
9
                    proto_tree_add_item(tree, hf_fcfzs_mbrid_fc, tvb,
169
9
                                          offset+4, 3, ENC_NA);
170
9
                    break;
171
0
                case FC_FZS_ZONEMBR_PWWN_LUN:
172
0
                    proto_tree_add_item(tree, hf_fcfzs_mbrid_fcwwn, tvb,
173
0
                                          offset+4, 8, ENC_NA);
174
0
                    proto_tree_add_item(tree, hf_fcfzs_mbrid_lun, tvb,
175
0
                                        offset+8, 8, ENC_NA);
176
0
                    break;
177
1
                case FC_FZS_ZONEMBR_DP_LUN:
178
1
                    proto_tree_add_item(tree, hf_fcfzs_mbrid_uint,
179
1
                                                 tvb, offset+4, 3, ENC_BIG_ENDIAN);
180
1
                    proto_tree_add_item(tree, hf_fcfzs_mbrid_lun, tvb,
181
1
                                        offset+4, 8, ENC_NA);
182
1
                    break;
183
0
                case FC_FZS_ZONEMBR_FCID_LUN:
184
0
                    proto_tree_add_item(tree, hf_fcfzs_mbrid_fc, tvb,
185
0
                                          offset+4, 3, ENC_NA);
186
0
                    proto_tree_add_item(tree, hf_fcfzs_mbrid_lun, tvb,
187
0
                                        offset+4, 8, ENC_NA);
188
0
                    break;
189
262
                default:
190
262
                    expert_add_info(pinfo, ti, &ei_fcfzs_mbrid);
191
321
                }
192
298
                offset += 12;
193
298
            }
194
93
        }
195
26
}
196
197
198
static void
199
dissect_fcfzs_gzc(tvbuff_t *tvb, unsigned offset, proto_tree *parent_tree, bool isreq)
200
0
{
201
0
    static int * const flags[] = {
202
0
        &hf_fcfzs_gzc_flags_hard_zones,
203
0
        &hf_fcfzs_gzc_flags_soft_zones,
204
0
        &hf_fcfzs_gzc_flags_zoneset_db,
205
0
        NULL
206
0
    };
207
208
0
    if (!isreq) {
209
0
        proto_tree_add_bitmask_with_flags(parent_tree, tvb, offset, hf_fcfzs_gzc_flags,
210
0
                                   ett_fcfzs_gzc_flags, flags, ENC_NA, BMT_NO_FALSE|BMT_NO_TFS);
211
212
0
        proto_tree_add_item(parent_tree, hf_fcfzs_gzc_vendor, tvb, offset+4, 4, ENC_BIG_ENDIAN);
213
0
    }
214
0
}
215
216
static void
217
dissect_fcfzs_gest(tvbuff_t *tvb, proto_tree *parent_tree, bool isreq)
218
0
{
219
0
    unsigned offset = 16;            /* past the fc_ct header */
220
0
    static int * const flags[] = {
221
0
        &hf_fcfzs_soft_zone_set_enforced,
222
0
        &hf_fcfzs_hard_zone_set_enforced,
223
0
        NULL
224
0
    };
225
226
0
    if (!isreq) {
227
0
        proto_tree_add_bitmask_with_flags(parent_tree, tvb, offset, hf_fcfzs_zone_state,
228
0
                                   ett_fcfzs_zone_state, flags, ENC_NA, BMT_NO_FALSE|BMT_NO_TFS);
229
230
0
        proto_tree_add_item(parent_tree, hf_fcfzs_gest_vendor, tvb, offset+4, 4, ENC_BIG_ENDIAN);
231
0
    }
232
0
}
233
234
static void
235
dissect_fcfzs_gzsn(tvbuff_t *tvb, proto_tree *tree, bool isreq)
236
0
{
237
0
    uint32_t numrec, i;
238
0
    uint32_t len;
239
0
    unsigned offset = 16;            /* past the fc_ct header */
240
241
0
    if (tree) {
242
0
        if (!isreq) {
243
0
            proto_tree_add_item_ret_uint(tree, hf_fcfzs_numzonesetattrs, tvb, offset,
244
0
                                4, ENC_BIG_ENDIAN, &numrec);
245
246
0
            offset += 4;
247
0
            for (i = 0; i < numrec; i++) {
248
0
                proto_tree_add_item_ret_uint(tree, hf_fcfzs_zonesetnmlen, tvb, offset,
249
0
                    1, ENC_BIG_ENDIAN, &len);
250
0
                proto_tree_add_item(tree, hf_fcfzs_zonesetname, tvb, offset+1,
251
0
                                    len, ENC_ASCII);
252
0
                offset += len + 1 + (len % 4);
253
0
                proto_tree_add_item(tree, hf_fcfzs_numzones, tvb, offset,
254
0
                                    4, ENC_BIG_ENDIAN);
255
0
                offset += 4;
256
0
            }
257
0
        }
258
0
    }
259
0
}
260
261
static void
262
dissect_fcfzs_gzd(tvbuff_t *tvb, proto_tree *tree, bool isreq)
263
0
{
264
0
    uint32_t numrec, i;
265
0
    uint32_t len;
266
0
    unsigned offset = 16;            /* past the fc_ct header */
267
268
0
    if (tree) {
269
0
        if (isreq) {
270
0
            proto_tree_add_item_ret_uint(tree, hf_fcfzs_zonesetnmlen, tvb, offset,
271
0
                1, ENC_BIG_ENDIAN, &len);
272
0
            proto_tree_add_item(tree, hf_fcfzs_zonesetname, tvb, offset+1,
273
0
                                len, ENC_ASCII);
274
0
        }
275
0
        else {
276
0
            proto_tree_add_item_ret_uint(tree, hf_fcfzs_numzonesetattrs, tvb, offset,
277
0
                4, ENC_BIG_ENDIAN, &numrec);
278
0
            offset += 4;
279
0
            for (i = 0; i < numrec; i++) {
280
0
                proto_tree_add_item_ret_uint(tree, hf_fcfzs_zonenmlen, tvb, offset,
281
0
                    1, ENC_BIG_ENDIAN, &len);
282
0
                proto_tree_add_item(tree, hf_fcfzs_zonename, tvb, offset+1,
283
0
                                    len, ENC_ASCII);
284
0
                offset += len + 1 + (len % 4);
285
0
                proto_tree_add_item(tree, hf_fcfzs_nummbrs, tvb, offset,
286
0
                                    4, ENC_BIG_ENDIAN);
287
0
                offset += 4;
288
0
            }
289
0
        }
290
0
    }
291
0
}
292
293
static void
294
dissect_fcfzs_gzm(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, bool isreq)
295
0
{
296
0
    uint32_t numrec, i, len, mbrtype;
297
0
    unsigned offset = 16;            /* past the fc_ct header */
298
0
    proto_item* ti;
299
300
0
        if (isreq) {
301
0
            proto_tree_add_item_ret_uint(tree, hf_fcfzs_zonenmlen, tvb, offset,
302
0
                1, ENC_BIG_ENDIAN, &len);
303
0
            proto_tree_add_item(tree, hf_fcfzs_zonename, tvb, offset+1,
304
0
                                len, ENC_ASCII);
305
0
        }
306
0
        else {
307
0
            proto_tree_add_item_ret_uint(tree, hf_fcfzs_nummbrentries, tvb, offset,
308
0
                                4, ENC_BIG_ENDIAN, &numrec);
309
0
            offset += 4;
310
0
            for (i = 0; i < numrec; i++) {
311
0
                ti = proto_tree_add_item_ret_uint(tree, hf_fcfzs_mbrtype, tvb, offset, 1, ENC_BIG_ENDIAN, &mbrtype);
312
0
                switch (mbrtype) {
313
0
                case FC_FZS_ZONEMBR_PWWN:
314
0
                case FC_FZS_ZONEMBR_NWWN:
315
0
                    proto_tree_add_item(tree, hf_fcfzs_mbrid_fcwwn, tvb,
316
0
                                          offset+4, 8, ENC_NA);
317
0
                    break;
318
0
                case FC_FZS_ZONEMBR_DP:
319
0
                    proto_tree_add_item(tree, hf_fcfzs_mbrid_uint,
320
0
                                                 tvb, offset+4, 3, ENC_BIG_ENDIAN);
321
0
                    break;
322
0
                case FC_FZS_ZONEMBR_FCID:
323
0
                    proto_tree_add_item(tree, hf_fcfzs_mbrid_fc, tvb,
324
0
                                          offset+4, 3, ENC_NA);
325
0
                    break;
326
0
                default:
327
0
                    expert_add_info(pinfo, ti, &ei_fcfzs_mbrid);
328
0
                }
329
0
                offset += 12;
330
0
            }
331
0
        }
332
0
}
333
334
static void
335
dissect_fcfzs_gazs(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, bool isreq)
336
0
{
337
0
    unsigned offset = 16;            /* past the fc_ct header */
338
339
0
    if (!isreq) {
340
0
        dissect_fcfzs_zoneset(tvb, pinfo, tree, offset);
341
0
    }
342
0
}
343
344
static void
345
dissect_fcfzs_gzs(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, bool isreq)
346
0
{
347
0
    unsigned offset = 16;            /* past the fc_ct header */
348
0
    uint32_t len;
349
350
0
    if (isreq) {
351
0
        proto_tree_add_item_ret_uint(tree, hf_fcfzs_zonesetnmlen, tvb, offset,
352
0
            1, ENC_BIG_ENDIAN, &len);
353
0
        proto_tree_add_item(tree, hf_fcfzs_zonesetname, tvb, offset+4,
354
0
                            len, ENC_ASCII);
355
0
    }
356
0
    else {
357
0
        dissect_fcfzs_zoneset(tvb, pinfo, tree, offset);
358
0
    }
359
0
}
360
361
static void
362
dissect_fcfzs_adzs(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, bool isreq)
363
26
{
364
26
    unsigned offset = 16;            /* past the fc_ct header */
365
366
26
    if (isreq) {
367
26
        dissect_fcfzs_zoneset(tvb, pinfo, tree, offset);
368
26
    }
369
26
}
370
371
static void
372
dissect_fcfzs_azsd(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, bool isreq)
373
0
{
374
0
    unsigned offset = 16;            /* past the fc_ct header */
375
376
0
    if (isreq) {
377
0
        dissect_fcfzs_zoneset(tvb, pinfo, tree, offset);
378
0
    }
379
0
}
380
381
static void
382
dissect_fcfzs_arzs(tvbuff_t *tvb, proto_tree *tree, bool isreq)
383
1
{
384
1
    unsigned offset = 16;            /* past the fc_ct header */
385
1
    uint32_t len;
386
387
1
    if (tree) {
388
1
        if (isreq) {
389
1
            proto_tree_add_item_ret_uint(tree, hf_fcfzs_zonesetnmlen, tvb, offset,
390
1
                1, ENC_BIG_ENDIAN, &len);
391
1
            proto_tree_add_item(tree, hf_fcfzs_zonesetname, tvb, offset+4,
392
1
                                len, ENC_ASCII);
393
1
        }
394
1
    }
395
1
}
396
397
static void
398
dissect_fcfzs_dzs(tvbuff_t *tvb _U_, proto_tree *tree _U_, bool isreq _U_)
399
1
{
400
    /* Both req & successful response contain just the FC_CT header */
401
1
    return;
402
1
}
403
404
static void
405
dissect_fcfzs_arzm(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, bool isreq)
406
16
{
407
16
    uint32_t numrec, i, len, plen, mbrtype;
408
16
    unsigned offset = 16;            /* past the fc_ct header */
409
16
    proto_item* ti;
410
411
16
        if (isreq) {
412
16
            proto_tree_add_item_ret_uint(tree, hf_fcfzs_zonenmlen, tvb, offset,
413
16
                1, ENC_BIG_ENDIAN, &len);
414
16
            proto_tree_add_item(tree, hf_fcfzs_zonename, tvb, offset+1,
415
16
                                len, ENC_ASCII);
416
417
16
            len += (len % 4);
418
16
            plen = tvb_reported_length(tvb) - offset - len;
419
420
16
            numrec = plen/12;   /* each mbr rec is 12 bytes long */
421
422
16
            offset += len;
423
251
            for (i = 0; i < numrec; i++) {
424
235
                ti = proto_tree_add_item_ret_uint(tree, hf_fcfzs_mbrtype, tvb, offset, 1, ENC_BIG_ENDIAN, &mbrtype);
425
235
                switch (mbrtype) {
426
2
                case FC_FZS_ZONEMBR_PWWN:
427
3
                case FC_FZS_ZONEMBR_NWWN:
428
3
                    proto_tree_add_item(tree, hf_fcfzs_mbrid_fcwwn, tvb,
429
3
                                          offset+4, 8, ENC_NA);
430
3
                    break;
431
22
                case FC_FZS_ZONEMBR_DP:
432
22
                    proto_tree_add_item(tree, hf_fcfzs_mbrid_uint,
433
22
                                                 tvb, offset+4, 3, ENC_BIG_ENDIAN);
434
22
                    break;
435
10
                case FC_FZS_ZONEMBR_FCID:
436
10
                    proto_tree_add_item(tree, hf_fcfzs_mbrid_fc, tvb,
437
10
                                          offset+4, 3, ENC_NA);
438
10
                    break;
439
200
                default:
440
200
                    expert_add_info(pinfo, ti, &ei_fcfzs_mbrid);
441
235
                }
442
235
                offset += 12;
443
235
            }
444
16
        }
445
16
}
446
447
static void
448
dissect_fcfzs_arzd(tvbuff_t *tvb, proto_tree *tree, bool isreq)
449
0
{
450
0
    unsigned offset = 16;            /* past the fc_ct header */
451
0
    uint32_t len;
452
453
0
    if (tree) {
454
0
        if (isreq) {
455
0
            proto_tree_add_item_ret_uint(tree, hf_fcfzs_zonesetnmlen, tvb, offset,
456
0
                1, ENC_BIG_ENDIAN, &len);
457
0
            proto_tree_add_item(tree, hf_fcfzs_zonesetname, tvb, offset+4,
458
0
                                len, ENC_ASCII);
459
0
            len += (len % 4);
460
0
            offset += len;
461
462
0
            proto_tree_add_item_ret_uint(tree, hf_fcfzs_zonenmlen, tvb, offset,
463
0
                1, ENC_BIG_ENDIAN, &len);
464
0
            proto_tree_add_item(tree, hf_fcfzs_zonename, tvb, offset+4,
465
0
                                len, ENC_ASCII);
466
0
        }
467
0
    }
468
0
}
469
470
static void
471
dissect_fcfzs_rjt(tvbuff_t *tvb, proto_tree *tree)
472
0
{
473
0
    unsigned offset = 0;
474
475
0
    if (tree) {
476
0
        proto_tree_add_item(tree, hf_fcfzs_reason, tvb, offset+13, 1, ENC_BIG_ENDIAN);
477
0
        proto_tree_add_item(tree, hf_fcfzs_rjtdetail, tvb, offset+14, 1, ENC_BIG_ENDIAN);
478
0
        proto_tree_add_item(tree, hf_fcfzs_rjtvendor, tvb, offset+15, 1, ENC_BIG_ENDIAN);
479
0
    }
480
0
}
481
482
static int
483
dissect_fcfzs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
484
51
{
485
486
/* Set up structures needed to add the protocol subtree and manage it */
487
51
    proto_item        *ti;
488
51
    proto_tree        *fcfzs_tree    = NULL;
489
51
    int                offset        = 0;
490
51
    fc_ct_preamble     cthdr;
491
51
    int                opcode;
492
51
    int                failed_opcode = 0;
493
51
    conversation_t    *conversation;
494
51
    fcfzs_conv_data_t *cdata;
495
51
    fcfzs_conv_key_t   ckey, *req_key;
496
51
    bool               isreq         = true;
497
51
    fc_hdr *fchdr;
498
499
    /* Reject the packet if data is NULL */
500
51
    if (data == NULL)
501
0
        return 0;
502
51
    fchdr = (fc_hdr *)data;
503
504
    /* Make entries in Protocol column and Info column on summary display */
505
51
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "Zone Server");
506
507
508
51
    tvb_memcpy(tvb, (uint8_t *)&cthdr, offset, FCCT_PRMBL_SIZE);
509
51
    cthdr.revision = tvb_get_uint8(tvb, offset+1);
510
51
    cthdr.in_id = tvb_get_ntoh24(tvb, offset);
511
51
    cthdr.opcode = g_ntohs(cthdr.opcode);
512
51
    opcode = cthdr.opcode;
513
51
    cthdr.maxres_size = g_ntohs(cthdr.maxres_size);
514
515
51
    if (tree) {
516
51
        ti = proto_tree_add_protocol_format(tree, proto_fcfzs, tvb, 0,
517
51
                                            tvb_captured_length(tvb),
518
51
                                            "Zone Server");
519
51
        fcfzs_tree = proto_item_add_subtree(ti, ett_fcfzs);
520
51
        proto_tree_add_item(fcfzs_tree, hf_fcfzs_opcode, tvb, offset+8, 2, ENC_BIG_ENDIAN);
521
51
        proto_tree_add_item(fcfzs_tree, hf_fcfzs_maxres_size, tvb, offset+10,
522
51
                            2, ENC_BIG_ENDIAN);
523
51
    }
524
525
51
    if ((opcode != FCCT_MSG_ACC) && (opcode != FCCT_MSG_RJT)) {
526
51
        conversation = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst,
527
51
                                         conversation_pt_to_conversation_type(pinfo->ptype), fchdr->oxid,
528
51
                                         fchdr->rxid, NO_PORT_B);
529
51
        if (!conversation) {
530
8
            conversation = conversation_new(pinfo->num, &pinfo->src, &pinfo->dst,
531
8
                                            conversation_pt_to_conversation_type(pinfo->ptype), fchdr->oxid,
532
8
                                            fchdr->rxid, NO_PORT2);
533
8
        }
534
535
51
        ckey.conv_idx = conversation->conv_index;
536
537
51
        cdata = (fcfzs_conv_data_t *)wmem_map_lookup(fcfzs_req_hash,
538
51
                                                         &ckey);
539
51
        if (cdata) {
540
            /* Since we never free the memory used by an exchange, this maybe a
541
             * case of another request using the same exchange as a previous
542
             * req.
543
             */
544
42
            cdata->opcode = opcode;
545
42
        }
546
9
        else {
547
9
            req_key = wmem_new(wmem_file_scope(), fcfzs_conv_key_t);
548
9
            req_key->conv_idx = conversation->conv_index;
549
550
9
            cdata = wmem_new(wmem_file_scope(), fcfzs_conv_data_t);
551
9
            cdata->opcode = opcode;
552
553
9
            wmem_map_insert(fcfzs_req_hash, req_key, cdata);
554
9
        }
555
556
51
        col_add_str(pinfo->cinfo, COL_INFO, val_to_str(pinfo->pool, opcode, fc_fzs_opcode_val,
557
51
                                                           "0x%x"));
558
51
    }
559
0
    else {
560
        /* Opcode is ACC or RJT */
561
0
        conversation = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst,
562
0
                                         conversation_pt_to_conversation_type(pinfo->ptype), fchdr->oxid,
563
0
                                         fchdr->rxid, NO_PORT_B);
564
0
        isreq = false;
565
0
        if (!conversation) {
566
0
            if (opcode == FCCT_MSG_ACC) {
567
0
                col_add_str(pinfo->cinfo, COL_INFO,
568
0
                                val_to_str(pinfo->pool, opcode, fc_fzs_opcode_val,
569
0
                                           "0x%x"));
570
                /* No record of what this accept is for. Can't decode */
571
0
                proto_tree_add_expert_format_remaining(fcfzs_tree, pinfo, &ei_fcfzs_no_exchange, tvb, 0,
572
0
                                    "No record of Exchg. Unable to decode MSG_ACC");
573
0
                return 0;
574
0
            }
575
0
        }
576
0
        else {
577
0
            ckey.conv_idx = conversation->conv_index;
578
579
0
            cdata = (fcfzs_conv_data_t *)wmem_map_lookup(fcfzs_req_hash, &ckey);
580
581
0
            if (cdata != NULL) {
582
0
                if (opcode == FCCT_MSG_ACC)
583
0
                    opcode = cdata->opcode;
584
0
                else
585
0
                    failed_opcode = cdata->opcode;
586
0
            }
587
588
0
            if (opcode != FCCT_MSG_RJT) {
589
0
                col_add_fstr(pinfo->cinfo, COL_INFO, "MSG_ACC (%s)",
590
0
                                val_to_str(pinfo->pool, opcode,
591
0
                                        fc_fzs_opcode_val, "0x%x"));
592
0
            }
593
0
            else {
594
0
                col_add_fstr(pinfo->cinfo, COL_INFO, "MSG_RJT (%s)",
595
0
                                val_to_str(pinfo->pool, failed_opcode,
596
0
                                        fc_fzs_opcode_val, "0x%x"));
597
0
            }
598
599
0
            if ((cdata == NULL) && (opcode != FCCT_MSG_RJT)) {
600
                /* No record of what this accept is for. Can't decode */
601
0
                proto_tree_add_expert_format_remaining(fcfzs_tree, pinfo, &ei_fcfzs_no_exchange, tvb, 0,
602
0
                                    "No record of Exchg. Unable to decode MSG_ACC/RJT");
603
0
                return 0;
604
0
            }
605
0
        }
606
0
    }
607
608
51
    switch (opcode) {
609
0
    case FCCT_MSG_RJT:
610
0
        dissect_fcfzs_rjt(tvb, fcfzs_tree);
611
0
        break;
612
0
    case FC_FZS_GZC:
613
0
        dissect_fcfzs_gzc(tvb, 16, fcfzs_tree, isreq);
614
0
        break;
615
0
    case FC_FZS_GEST:
616
0
        dissect_fcfzs_gest(tvb, fcfzs_tree, isreq);
617
0
        break;
618
0
    case FC_FZS_GZSN:
619
0
        dissect_fcfzs_gzsn(tvb, fcfzs_tree, isreq);
620
0
        break;
621
0
    case FC_FZS_GZD:
622
0
        dissect_fcfzs_gzd(tvb, fcfzs_tree, isreq);
623
0
        break;
624
0
    case FC_FZS_GZM:
625
0
        dissect_fcfzs_gzm(tvb, pinfo, fcfzs_tree, isreq);
626
0
        break;
627
0
    case FC_FZS_GAZS:
628
0
        dissect_fcfzs_gazs(tvb, pinfo, fcfzs_tree, isreq);
629
0
        break;
630
0
    case FC_FZS_GZS:
631
0
        dissect_fcfzs_gzs(tvb, pinfo, fcfzs_tree, isreq);
632
0
        break;
633
26
    case FC_FZS_ADZS:
634
26
        dissect_fcfzs_adzs(tvb, pinfo, fcfzs_tree, isreq);
635
26
        break;
636
0
    case FC_FZS_AZSD:
637
0
        dissect_fcfzs_azsd(tvb, pinfo, fcfzs_tree, isreq);
638
0
        break;
639
1
    case FC_FZS_AZS:
640
1
        dissect_fcfzs_arzs(tvb, fcfzs_tree, isreq);
641
1
        break;
642
1
    case FC_FZS_DZS:
643
1
        dissect_fcfzs_dzs(tvb, fcfzs_tree, isreq);
644
1
        break;
645
0
    case FC_FZS_AZM:
646
0
        dissect_fcfzs_arzm(tvb, pinfo, fcfzs_tree, isreq);
647
0
        break;
648
0
    case FC_FZS_AZD:
649
0
        dissect_fcfzs_arzd(tvb, fcfzs_tree, isreq);
650
0
        break;
651
16
    case FC_FZS_RZM:
652
16
        dissect_fcfzs_arzm(tvb, pinfo, fcfzs_tree, isreq);
653
16
        break;
654
0
    case FC_FZS_RZD:
655
0
        dissect_fcfzs_arzd(tvb, fcfzs_tree, isreq);
656
0
        break;
657
0
    case FC_FZS_RZS:
658
0
        dissect_fcfzs_arzs(tvb, fcfzs_tree, isreq);
659
0
        break;
660
7
    default:
661
7
        call_data_dissector(tvb, pinfo, tree);
662
7
        break;
663
51
    }
664
665
26
    return tvb_captured_length(tvb);
666
51
}
667
668
/* Register the protocol with Wireshark */
669
670
void
671
proto_register_fcfzs(void)
672
16
{
673
674
16
    static hf_register_info hf[] = {
675
16
        { &hf_fcfzs_opcode,
676
16
          {"Opcode", "fcfzs.opcode",
677
16
           FT_UINT16, BASE_HEX, VALS(fc_fzs_opcode_val), 0x0,
678
16
           NULL, HFILL}},
679
680
16
        { &hf_fcfzs_gzc_vendor,
681
16
          {"Vendor Specific Flags", "fcfzs.gzc.vendor",
682
16
           FT_UINT32, BASE_HEX, NULL, 0x0,
683
16
           NULL, HFILL}},
684
685
16
        { &hf_fcfzs_gest_vendor,
686
16
          {"Vendor Specific State", "fcfzs.gest.vendor",
687
16
           FT_UINT32, BASE_HEX, NULL, 0x0,
688
16
           NULL, HFILL}},
689
690
16
        { &hf_fcfzs_numzoneattrs,
691
16
          {"Number of Zone Attribute Entries", "fcfzs.zone.numattrs",
692
16
           FT_UINT32, BASE_DEC, NULL, 0x0,
693
16
           NULL, HFILL}},
694
695
16
        { &hf_fcfzs_zonesetnmlen,
696
16
          {"Zone Set Name Length", "fcfzs.zoneset.namelen",
697
16
           FT_UINT8, BASE_DEC, NULL, 0x0,
698
16
           NULL, HFILL}},
699
700
16
        { &hf_fcfzs_zonesetname,
701
16
          {"Zone Set Name", "fcfzs.zoneset.name",
702
16
           FT_STRING, BASE_NONE, NULL, 0x0,
703
16
           NULL, HFILL}},
704
705
16
        { &hf_fcfzs_numzones,
706
16
          {"Number of Zones", "fcfzs.zoneset.numzones",
707
16
           FT_UINT32, BASE_DEC, NULL, 0x0,
708
16
           NULL, HFILL}},
709
710
16
        { &hf_fcfzs_numzonesetattrs,
711
16
          {"Number of Zone Set Attribute Entries", "fcfzs.zoneset.numattrs",
712
16
           FT_UINT32, BASE_DEC, NULL, 0x0,
713
16
           NULL, HFILL}},
714
715
16
        { &hf_fcfzs_zonenmlen,
716
16
          {"Zone Name Length", "fcfzs.zone.namelen",
717
16
           FT_UINT8, BASE_DEC, NULL, 0x0,
718
16
           NULL, HFILL}},
719
720
16
        { &hf_fcfzs_zonename,
721
16
          {"Zone Name", "fcfzs.zone.name",
722
16
           FT_STRING, BASE_NONE, NULL, 0x0,
723
16
           NULL, HFILL}},
724
725
16
        { &hf_fcfzs_nummbrs,
726
16
          {"Number of Zone Members", "fcfzs.zone.nummbrs",
727
16
           FT_UINT32, BASE_DEC, NULL, 0x0,
728
16
           NULL, HFILL}},
729
730
16
        { &hf_fcfzs_nummbrentries,
731
16
          {"Number of Zone Member Attribute Entries", "fcfzs.zonembr.numattrs",
732
16
           FT_UINT32, BASE_DEC, NULL, 0x0,
733
16
           NULL, HFILL}},
734
735
16
        { &hf_fcfzs_mbrtype,
736
16
          {"Zone Member Identifier Type", "fcfzs.zonembr.idtype",
737
16
           FT_UINT8, BASE_HEX, VALS(fc_fzs_zonembr_type_val), 0x0,
738
16
           NULL, HFILL}},
739
740
#if 0
741
        { &hf_fcfzs_mbridlen,
742
          {"Zone Member Identifier Length", "fcfzs.zonembr.idlen",
743
           FT_UINT8, BASE_DEC, NULL, 0x0,
744
           NULL, HFILL}},
745
#endif
746
747
16
        { &hf_fcfzs_mbrid_fcwwn,
748
16
          {"Zone Member Identifier", "fcfzs.zone.mbrid.fcwwn",
749
16
           FT_FCWWN, BASE_NONE, NULL, 0x0,
750
16
           NULL, HFILL}},
751
752
16
        { &hf_fcfzs_mbrid_fc,
753
16
          {"Zone Member Identifier", "fcfzs.zone.mbrid.fc",
754
16
           FT_BYTES, SEP_DOT, NULL, 0x0,
755
16
           NULL, HFILL}},
756
757
16
        { &hf_fcfzs_mbrid_uint,
758
16
          {"Zone Member Identifier", "fcfzs.zone.mbrid.uint",
759
16
           FT_UINT24, BASE_HEX, NULL, 0x0,
760
16
           NULL, HFILL}},
761
762
16
        { &hf_fcfzs_reason,
763
16
          {"Reason Code", "fcfzs.reason",
764
16
           FT_UINT8, BASE_HEX, VALS(fc_ct_rjt_code_vals), 0x0,
765
16
           NULL, HFILL}},
766
767
16
        { &hf_fcfzs_rjtdetail,
768
16
          {"Reason Code Explanation", "fcfzs.rjtdetail",
769
16
           FT_UINT8, BASE_HEX, VALS(fc_fzs_rjt_code_val), 0x0,
770
16
           NULL, HFILL}},
771
772
16
        { &hf_fcfzs_rjtvendor,
773
16
          {"Vendor Specific Reason", "fcfzs.rjtvendor",
774
16
           FT_UINT8, BASE_HEX, NULL, 0x0,
775
16
           NULL, HFILL}},
776
777
16
        { &hf_fcfzs_maxres_size,
778
16
          {"Maximum/Residual Size", "fcfzs.maxres_size",
779
16
           FT_UINT16, BASE_DEC, NULL, 0x0,
780
16
           NULL, HFILL}},
781
782
16
        { &hf_fcfzs_mbrid_lun,
783
16
          {"LUN", "fcfzs.zone.lun",
784
16
           FT_BYTES, BASE_NONE, NULL, 0x0,
785
16
           NULL, HFILL}},
786
787
16
        { &hf_fcfzs_gzc_flags,
788
16
          {"Capabilities", "fcfzs.gzc.flags",
789
16
           FT_UINT8, BASE_HEX, NULL, 0x0,
790
16
           NULL, HFILL}},
791
792
16
        { &hf_fcfzs_gzc_flags_hard_zones,
793
16
          {"Hard Zones", "fcfzs.gzc.flags.hard_zones",
794
16
           FT_BOOLEAN, 8, TFS(&tfs_supported_not_supported), 0x80,
795
16
           NULL, HFILL}},
796
797
16
        { &hf_fcfzs_gzc_flags_soft_zones,
798
16
          {"Soft Zones", "fcfzs.gzc.flags.soft_zones",
799
16
           FT_BOOLEAN, 8, TFS(&tfs_supported_not_supported), 0x40,
800
16
           NULL, HFILL}},
801
802
16
        { &hf_fcfzs_gzc_flags_zoneset_db,
803
16
          {"ZoneSet Database", "fcfzs.gzc.flags.zoneset_db",
804
16
           FT_BOOLEAN, 8, TFS(&tfs_available_not_available), 0x01,
805
16
           NULL, HFILL}},
806
807
16
        { &hf_fcfzs_zone_state,
808
16
          {"Zone State", "fcfzs.zone.state",
809
16
           FT_UINT8, BASE_HEX, NULL, 0x0,
810
16
           NULL, HFILL}},
811
812
16
        { &hf_fcfzs_soft_zone_set_enforced,
813
16
          {"Soft Zone Set", "fcfzs.soft_zone_set.enforced",
814
16
           FT_BOOLEAN, 8, TFS(&tfs_enforced_not_enforced), 0x80,
815
16
           NULL, HFILL}},
816
817
16
        { &hf_fcfzs_hard_zone_set_enforced,
818
16
          {"Hard Zone Set", "fcfzs.hard_zone_set.enforced",
819
16
           FT_BOOLEAN, 8, TFS(&tfs_enforced_not_enforced), 0x40,
820
16
           NULL, HFILL}},
821
822
16
    };
823
824
16
    static int *ett[] = {
825
16
        &ett_fcfzs,
826
16
        &ett_fcfzs_gzc_flags,
827
16
        &ett_fcfzs_zone_state,
828
16
    };
829
830
16
    static ei_register_info ei[] = {
831
16
        { &ei_fcfzs_no_exchange, { "fcfzs.no_exchange", PI_UNDECODED, PI_WARN, "No record of Exchg. Unable to decode", EXPFILL }},
832
16
        { &ei_fcfzs_mbrid, { "fcfzs.mbrid.unknown_type", PI_PROTOCOL, PI_WARN, "Unknown member type format", EXPFILL }},
833
16
    };
834
835
16
    expert_module_t* expert_fcfzs;
836
837
16
    proto_fcfzs = proto_register_protocol("Fibre Channel Fabric Zone Server", "FC FZS", "fcfzs");
838
839
16
    proto_register_field_array(proto_fcfzs, hf, array_length(hf));
840
16
    proto_register_subtree_array(ett, array_length(ett));
841
16
    expert_fcfzs = expert_register_protocol(proto_fcfzs);
842
16
    expert_register_field_array(expert_fcfzs, ei, array_length(ei));
843
844
16
    fcfzs_req_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), fcfzs_hash, fcfzs_equal);
845
846
16
    fzs_handle = register_dissector("fcfzs", dissect_fcfzs, proto_fcfzs);
847
16
}
848
849
void
850
proto_reg_handoff_fcfzs(void)
851
16
{
852
16
    dissector_add_uint("fcct.server", FCCT_GSRVR_FZS, fzs_handle);
853
16
}
854
855
/*
856
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
857
 *
858
 * Local variables:
859
 * c-basic-offset: 4
860
 * tab-width: 8
861
 * indent-tabs-mode: nil
862
 * End:
863
 *
864
 * vi: set shiftwidth=4 tabstop=8 expandtab:
865
 * :indentSize=4:tabSize=8:noTabs=true:
866
 */