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-nxp_802154_sniffer.c
Line
Count
Source
1
/* packet-nxp_802154_sniffer.c
2
 * Routines for NXP JN51xx 802.15.4 Sniffer application packet dissection
3
 * Copyright 2017, Lee Mitchell <lee@indigopepper.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
 * This dissector handles messages sent by either NXP's own sniffer server application,
14
 * or the open source one provided on GitHub here:
15
 * https://github.com/Codemonkey1973/JN51xx-802.15.4-Sniffer-Server
16
 *
17
 * When used with an NXP JN51xx wireless microcontroller running NXP's
18
 * Sniffer firmware, the sniffer server prefixes any received packets
19
 * with a short header and then sends them as a UDP datagrams. This dissector
20
 * decodes the short header and then passes the 802.15.4 frame on to the
21
 * IEEE 802.15.4 dissector for further dissection.
22
 *
23
 */
24
#include "config.h"
25
26
#include <epan/packet.h>
27
#include <epan/exceptions.h>
28
#include "packet-ieee802154.h"
29
30
16
#define NXP_802154_SNIFFER_UDP_PORT             49999 /* Not IANA registered */
31
9
#define NXP_802154_SNIFFER_TIMESTAMP_LENGTH     5
32
33
void proto_reg_handoff_nxp_802154_sniffer(void);
34
void proto_register_nxp_802154_sniffer(void);
35
36
static int proto_nxp_802154_sniffer;
37
38
static int hf_nxp_802154_sniffer_timestamp;
39
static int hf_nxp_802154_sniffer_id;
40
static int hf_nxp_802154_sniffer_channel;
41
static int hf_nxp_802154_sniffer_lqi;
42
static int hf_nxp_802154_sniffer_length;
43
44
static int ett_nxp_802154_sniffer;
45
46
static dissector_handle_t nxp_802154_sniffer_handle;
47
static dissector_handle_t ieee802154_handle;
48
49
static bool
50
test_nxp_802154_sniffer(tvbuff_t *tvb, unsigned offset)
51
9
{
52
9
    volatile bool valid = true;
53
9
    uint8_t channel, frame_len;
54
55
9
    TRY {
56
        /* Skip Timestamp */
57
9
        offset += NXP_802154_SNIFFER_TIMESTAMP_LENGTH;
58
        /* ID must be a null terminated ASCII string.
59
         * tvb_strsize can throw exceptions caught by CATCH_BOUNDS_ERRORS. */
60
9
        offset += tvb_strsize(tvb, offset);
61
        /* Channel must be between 11 and 26 (2.4 GHz PHY)
62
         * XXX: In the future the channels below 11 (868 and 915 MHz PHY)
63
         * might be possible */
64
9
        channel = tvb_get_uint8(tvb, offset);
65
9
        if (channel < 11 || channel > 26) {
66
6
            valid = false;
67
6
        }
68
        /* Skip LQI, it can take any value from 0x00 to 0xff */
69
9
        offset += 2;
70
9
        frame_len = tvb_get_uint8(tvb, offset);
71
9
        if (frame_len < IEEE802154_FCS_LEN || frame_len > IEEE802154_PHY_LENGTH_MASK) {
72
2
            valid = false;
73
2
        }
74
9
        offset += 1;
75
9
        if (tvb_reported_length_remaining(tvb, offset) != frame_len) {
76
6
            valid = false;
77
6
        }
78
9
    }
79
9
    CATCH_BOUNDS_ERRORS {
80
3
        valid = false;
81
3
    }
82
9
    ENDTRY;
83
84
9
    return valid;
85
9
}
86
87
static int
88
dissect_nxp_802154_sniffer(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
89
12
{
90
12
    proto_item *ti;
91
12
    proto_tree *nxp_802154_sniffer_tree;
92
12
    unsigned offset = 0;
93
12
    unsigned snifferidlen;
94
95
12
    tvbuff_t *ieee802154_tvb;
96
97
    /* Check that the packet is long enough for it to belong to us. */
98
12
    if (tvb_reported_length(tvb) < 9)
99
3
        return 0;
100
101
9
    if (!test_nxp_802154_sniffer(tvb, offset)) {
102
9
        return 0;
103
9
    }
104
105
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "NXP 802.15.4 SNIFFER");
106
0
    col_clear(pinfo->cinfo, COL_INFO);
107
108
0
    ti = proto_tree_add_item(tree, proto_nxp_802154_sniffer, tvb, offset, -1, ENC_NA);
109
0
    nxp_802154_sniffer_tree = proto_item_add_subtree(ti, ett_nxp_802154_sniffer);
110
111
    /* Time stamp */
112
0
    proto_tree_add_item(nxp_802154_sniffer_tree, hf_nxp_802154_sniffer_timestamp, tvb, offset, NXP_802154_SNIFFER_TIMESTAMP_LENGTH, ENC_BIG_ENDIAN);
113
0
    offset += NXP_802154_SNIFFER_TIMESTAMP_LENGTH;
114
115
    /* ID */
116
0
    proto_tree_add_item_ret_length(nxp_802154_sniffer_tree, hf_nxp_802154_sniffer_id, tvb, offset, -1, ENC_ASCII|ENC_NA, &snifferidlen);
117
0
    offset += snifferidlen;
118
119
    /* Channel */
120
0
    proto_tree_add_item(nxp_802154_sniffer_tree, hf_nxp_802154_sniffer_channel, tvb, offset, 1, ENC_BIG_ENDIAN);
121
0
    offset += 1;
122
123
    /* LQI */
124
0
    proto_tree_add_item(nxp_802154_sniffer_tree, hf_nxp_802154_sniffer_lqi, tvb, offset, 1, ENC_BIG_ENDIAN);
125
0
    offset += 1;
126
127
    /* Length */
128
0
    proto_tree_add_item(nxp_802154_sniffer_tree, hf_nxp_802154_sniffer_length, tvb, offset, 1, ENC_BIG_ENDIAN);
129
0
    offset += 1;
130
131
0
    ieee802154_tvb = tvb_new_subset_remaining(tvb, offset);
132
0
    call_dissector(ieee802154_handle, ieee802154_tvb, pinfo, tree);
133
134
0
    return tvb_captured_length(tvb);
135
9
}
136
137
138
void
139
proto_register_nxp_802154_sniffer(void)
140
16
{
141
16
    static hf_register_info hf[] = {
142
16
        { &hf_nxp_802154_sniffer_timestamp,
143
16
          { "Timestamp (16uS Symbol Periods)",  "nxp_802154_sniffer.timestamp", FT_UINT40,  BASE_DEC,   NULL, 0x0, NULL, HFILL } },
144
16
        { &hf_nxp_802154_sniffer_id,
145
16
          { "Sniffer ID",                       "nxp_802154_sniffer.id",        FT_STRINGZ, BASE_NONE,  NULL, 0x0, NULL, HFILL } },
146
16
        { &hf_nxp_802154_sniffer_channel,
147
16
          { "Channel",                          "nxp_802154_sniffer.channel",   FT_UINT8,   BASE_DEC,   NULL, 0x0, NULL, HFILL } },
148
16
        { &hf_nxp_802154_sniffer_lqi,
149
16
          { "LQI",                              "nxp_802154_sniffer.lqi",       FT_UINT8,   BASE_DEC,   NULL, 0x0, NULL, HFILL } },
150
16
        { &hf_nxp_802154_sniffer_length,
151
16
          { "Length",                           "nxp_802154_sniffer.length",    FT_UINT8,   BASE_DEC,   NULL, 0x0, NULL, HFILL } },
152
16
    };
153
154
16
    static int *ett[] = {
155
16
       &ett_nxp_802154_sniffer,
156
16
    };
157
158
16
    proto_nxp_802154_sniffer = proto_register_protocol("NXP 802.15.4 Sniffer Protocol",
159
16
                                               "NXP 802154 Sniffer",
160
16
                                               "nxp_802154_sniffer");
161
16
    proto_register_field_array(proto_nxp_802154_sniffer, hf, array_length(hf));
162
16
    proto_register_subtree_array(ett, array_length(ett));
163
164
16
    nxp_802154_sniffer_handle = register_dissector("nxp_802154_sniffer", dissect_nxp_802154_sniffer, proto_nxp_802154_sniffer);
165
16
}
166
167
void
168
proto_reg_handoff_nxp_802154_sniffer(void)
169
16
{
170
    /* FCS type is user-specified */
171
16
    ieee802154_handle = find_dissector_add_dependency("wpan", proto_nxp_802154_sniffer);
172
173
16
    dissector_add_uint_with_preference("udp.port", NXP_802154_SNIFFER_UDP_PORT, nxp_802154_sniffer_handle);
174
16
}
175
176
/*
177
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
178
 *
179
 * Local variables:
180
 * c-basic-offset: 4
181
 * tab-width: 8
182
 * indent-tabs-mode: nil
183
 * End:
184
 *
185
 * vi: set shiftwidth=4 tabstop=8 expandtab:
186
 * :indentSize=4:tabSize=8:noTabs=true:
187
 */