/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 | | */ |