Coverage Report

Created: 2025-02-15 06:25

/src/wireshark/epan/dissectors/packet-qllc.c
Line
Count
Source (jump to first uncovered line)
1
/* packet-qllc.c
2
 * Routines for QLLC protocol - Qualified? LLC
3
 * Gilbert Ramirez <gram@alumni.rice.edu>
4
 *
5
 * Wireshark - Network traffic analyzer
6
 * By Gerald Combs <gerald@wireshark.org>
7
 * Copyright 2001 Gerald Combs
8
 *
9
 * SPDX-License-Identifier: GPL-2.0-or-later
10
 */
11
12
#include "config.h"
13
14
#include <epan/packet.h>
15
16
void proto_register_qllc(void);
17
void proto_reg_handoff_qllc(void);
18
19
static int proto_qllc;
20
static int hf_qllc_address;
21
static int hf_qllc_control;
22
23
static int ett_qllc;
24
25
static dissector_handle_t sna_handle;
26
27
#define QSM                 0x93
28
#define QDISC               0x53
29
0
#define QXID                0xbf
30
0
#define QTEST               0xf3
31
0
#define QRR                 0xf1
32
#define QRD                 0x53
33
#define QUA                 0x73
34
#define QDM                 0x1f
35
0
#define QFRMR               0x97
36
#define QUI                 0x03
37
#define QUI_NO_REPLY        0x13
38
#define QSIM                0x17
39
40
0
#define QRD_QDISC_VALUE     0x53
41
0
#define QDISC_TEXT          "QDISC"
42
0
#define QRD_TEXT            "QRD"
43
44
/* Control Field */
45
static const value_string qllc_control_vals[] = {
46
    { QUI,          "QUI" },
47
    { QUI_NO_REPLY, "QUI - reply required" },
48
    { QSIM,         "QSIM" },
49
    { QDM,          "QDM" },
50
    { QUA,          "QUA" },
51
    { QSM,          "QSM" },
52
    { QFRMR,        "QFRMR" },
53
    { QXID,         "QXID" },
54
    { QRR,          "QRR" },
55
    { QTEST,        "QTEST" },
56
    { QDISC,        "QDISC / QRD" }, /* Same value for QDISC and QRD (following it is a COMMAND or RESPONSE) */
57
    { 0x00, NULL },
58
};
59
60
61
static int
62
dissect_qllc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
63
0
{
64
0
    proto_tree *qllc_tree;
65
0
    proto_item *qllc_ti;
66
0
    bool       *q_bit_set;
67
0
    uint8_t     addr, ctrl;
68
0
    bool        command = false;
69
70
    /* Reject the packet if data is NULL */
71
0
    if (data == NULL)
72
0
        return 0;
73
0
    q_bit_set = (bool *)data;
74
75
    /*
76
     * If the Q bit isn't set, this is just SNA data.
77
     */
78
0
    if (!(*q_bit_set)) {
79
0
        call_dissector(sna_handle, tvb, pinfo, tree);
80
0
        return tvb_captured_length(tvb);
81
0
    }
82
83
    /* Summary information */
84
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "QLLC");
85
0
    col_clear(pinfo->cinfo, COL_INFO);
86
87
0
    qllc_ti = proto_tree_add_item(tree, proto_qllc, tvb, 0, -1, ENC_NA);
88
0
    qllc_tree = proto_item_add_subtree(qllc_ti, ett_qllc);
89
90
    /* Get the address; we need it to determine if this is a
91
     * COMMAND or a RESPONSE */
92
0
    addr = tvb_get_uint8(tvb, 0);
93
0
    proto_tree_add_item(qllc_tree, hf_qllc_address, tvb, 0, 1, ENC_BIG_ENDIAN);
94
95
    /* The address field equals X'FF' in commands (except QRR)
96
     * and anything in responses. */
97
0
    ctrl = tvb_get_uint8(tvb, 1);
98
0
    if (ctrl != QRR && addr == 0xff) {
99
0
        command = true;
100
0
    }
101
102
103
    /* Disambiguate QRD_QDISC_VALUE, based on whether this packet is
104
     * a COMMAND or RESPONSE. */
105
0
    if (ctrl == QRD_QDISC_VALUE) {
106
0
        if (command) {
107
0
            col_set_str(pinfo->cinfo, COL_INFO, QDISC_TEXT);
108
0
            proto_tree_add_uint_format_value(qllc_tree, hf_qllc_control, tvb,
109
0
                    1, 1, ctrl, "%s (0x%02x)", QDISC_TEXT, ctrl);
110
0
        }
111
0
        else {
112
0
            col_set_str(pinfo->cinfo, COL_INFO, QRD_TEXT);
113
0
            proto_tree_add_uint_format_value(qllc_tree, hf_qllc_control, tvb,
114
0
                    1, 1, ctrl, "%s (0x%02x)", QRD_TEXT, ctrl);
115
0
        }
116
0
    }
117
0
    else {
118
        /* Non-ambiguous control field value */
119
0
        col_add_str(pinfo->cinfo, COL_INFO,
120
0
                    val_to_str(ctrl, qllc_control_vals,
121
0
                        "Control Field: 0x%02x (unknown)"));
122
123
0
        proto_tree_add_uint(qllc_tree, hf_qllc_control, tvb,
124
0
                    1, 1, ctrl);
125
0
    }
126
127
    /* Do we have an I field ? */
128
    /* XXX - I field exists for QUI too, but only for subarea nodes.
129
     * Need to test for this. */
130
0
    if (ctrl == QXID || ctrl == QTEST || ctrl == QFRMR) {
131
        /* yes */
132
0
    }
133
134
0
    return tvb_captured_length(tvb);
135
0
}
136
137
void
138
proto_register_qllc(void)
139
14
{
140
14
    static hf_register_info hf[] = {
141
14
        { &hf_qllc_address,
142
14
          { "Address Field", "qllc.address", FT_UINT8, BASE_HEX, NULL, 0x0,
143
14
            NULL, HFILL }},
144
145
14
        { &hf_qllc_control,
146
14
          { "Control Field", "qllc.control", FT_UINT8, BASE_HEX,
147
14
            VALS(qllc_control_vals), 0x0, NULL, HFILL }},
148
14
    };
149
150
14
    static int *ett[] = {
151
14
        &ett_qllc,
152
14
    };
153
154
14
    proto_qllc = proto_register_protocol("Qualified Logical Link Control", "QLLC", "qllc");
155
14
    proto_register_field_array(proto_qllc, hf, array_length(hf));
156
14
    proto_register_subtree_array(ett, array_length(ett));
157
14
    register_dissector("qllc", dissect_qllc, proto_qllc);
158
14
}
159
160
void
161
proto_reg_handoff_qllc(void)
162
14
{
163
14
    sna_handle = find_dissector_add_dependency("sna", proto_qllc);
164
14
}
165
166
/*
167
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
168
 *
169
 * Local variables:
170
 * c-basic-offset: 4
171
 * tab-width: 8
172
 * indent-tabs-mode: nil
173
 * End:
174
 *
175
 * vi: set shiftwidth=4 tabstop=8 expandtab:
176
 * :indentSize=4:tabSize=8:noTabs=true:
177
 */