Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-zep.c
bloba7ce6c19b0fa443c286158a44e3c822ddfe88c3b
1 /* packet-zep.c
2 * Dissector routines for the ZigBee Encapsulation Protocol
3 * By Owen Kirby <osk@exegin.com>
4 * Copyright 2009 Exegin Technologies Limited
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 *------------------------------------------------------------
13 * ZEP Packets must be received in the following format:
14 * |UDP Header| ZEP Header |IEEE 802.15.4 Packet|
15 * | 8 bytes | 16/32 bytes | <= 127 bytes |
16 *------------------------------------------------------------
18 * ZEP v1 Header will have the following format:
19 * |Preamble|Version|Channel ID|Device ID|CRC/LQI Mode|LQI Val|Reserved|Length|
20 * |2 bytes |1 byte | 1 byte | 2 bytes | 1 byte |1 byte |7 bytes |1 byte|
22 * ZEP v2 Header will have the following format (if type=1/Data):
23 * |Preamble|Version| Type |Channel ID|Device ID|CRC/LQI Mode|LQI Val|NTP Timestamp|Sequence#|Reserved|Length|
24 * |2 bytes |1 byte |1 byte| 1 byte | 2 bytes | 1 byte |1 byte | 8 bytes | 4 bytes |10 bytes|1 byte|
26 * ZEP v2 Header will have the following format (if type=2/Ack):
27 * |Preamble|Version| Type |Sequence#|
28 * |2 bytes |1 byte |1 byte| 4 bytes |
29 *------------------------------------------------------------
32 #include "config.h"
35 #include <epan/packet.h>
36 #include <epan/tfs.h>
37 #include <epan/unit_strings.h>
38 #include <wsutil/array.h>
40 /* Function declarations */
41 void proto_reg_handoff_zep(void);
42 void proto_register_zep(void);
44 #define ZEP_DEFAULT_PORT 17754
46 /* ZEP Preamble Code */
47 #define ZEP_PREAMBLE "EX"
49 /* ZEP Header lengths. */
50 #define ZEP_V1_HEADER_LEN 16
51 #define ZEP_V2_HEADER_LEN 32
52 #define ZEP_V2_ACK_LEN 8
54 #define ZEP_V2_TYPE_DATA 1
55 #define ZEP_V2_TYPE_ACK 2
57 #define ZEP_LENGTH_MASK 0x7F
59 static const range_string type_rvals[] = {
60 {0, 0, "Reserved"},
61 {ZEP_V2_TYPE_DATA, ZEP_V2_TYPE_DATA, "Data"},
62 {ZEP_V2_TYPE_ACK, ZEP_V2_TYPE_ACK, "Ack"},
63 {3, 255, "Reserved" },
64 {0, 0, NULL}
68 static const true_false_string tfs_crc_lqi = { "CRC", "LQI" };
70 /* Initialize protocol and registered fields. */
71 static int proto_zep;
72 static int hf_zep_version;
73 static int hf_zep_type;
74 static int hf_zep_channel_id;
75 static int hf_zep_device_id;
76 static int hf_zep_lqi_mode;
77 static int hf_zep_lqi;
78 static int hf_zep_timestamp;
79 static int hf_zep_seqno;
80 static int hf_zep_ieee_length;
81 static int hf_zep_protocol_id;
82 static int hf_zep_reserved_field;
84 /* Initialize protocol subtrees. */
85 static int ett_zep;
87 /* Dissector handle */
88 static dissector_handle_t zep_handle;
90 /* Subdissector handles */
91 static dissector_handle_t ieee802154_handle;
92 static dissector_handle_t ieee802154_cc24xx_handle;
94 /*FUNCTION:------------------------------------------------------
95 * NAME
96 * dissect_zep
97 * DESCRIPTION
98 * IEEE 802.15.4 packet dissection routine for Wireshark.
99 * PARAMETERS
100 * tvbuff_t *tvb - pointer to buffer containing raw packet.
101 * packet_info *pinfo - pointer to packet information fields
102 * proto_tree *tree - pointer to data tree Wireshark uses to display packet.
103 * RETURNS
104 * void
105 *---------------------------------------------------------------
107 static int dissect_zep(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
109 tvbuff_t *next_tvb;
110 proto_item *proto_root;
111 proto_tree *zep_tree;
112 uint8_t ieee_packet_len;
113 uint8_t zep_header_len;
114 uint8_t version;
115 uint8_t type;
116 uint32_t channel_id, seqno;
117 bool lqi_mode = false;
119 dissector_handle_t next_dissector;
121 if (tvb_reported_length(tvb) < ZEP_V2_ACK_LEN)
122 return 0;
124 /* Determine whether this is a Q51/IEEE 802.15.4 sniffer packet or not */
125 if(strcmp(tvb_get_string_enc(pinfo->pool, tvb, 0, 2, ENC_ASCII), ZEP_PREAMBLE)){
126 /* This is not a Q51/ZigBee sniffer packet */
127 return 0;
130 /* Extract the protocol version from the ZEP header. */
131 version = tvb_get_uint8(tvb, 2);
132 if (version == 1) {
133 /* Type indicates a ZEP_v1 packet. */
135 zep_header_len = ZEP_V1_HEADER_LEN;
136 if (tvb_reported_length(tvb) < ZEP_V1_HEADER_LEN)
137 return 0;
139 type = 0;
140 ieee_packet_len = (tvb_get_uint8(tvb, ZEP_V1_HEADER_LEN - 1) & ZEP_LENGTH_MASK);
142 else {
143 /* At the time of writing, v2 is the latest version of ZEP, assuming
144 * anything higher than v2 has identical format. */
146 type = tvb_get_uint8(tvb, 3);
147 if (type == ZEP_V2_TYPE_ACK) {
148 /* ZEP Ack has only the seqno. */
149 zep_header_len = ZEP_V2_ACK_LEN;
150 ieee_packet_len = 0;
152 else {
153 /* Although, only type 1 corresponds to data, if another value is present, assume it is dissected the same. */
154 zep_header_len = ZEP_V2_HEADER_LEN;
155 if (tvb_reported_length(tvb) < ZEP_V2_HEADER_LEN)
156 return 0;
158 ieee_packet_len = (tvb_get_uint8(tvb, ZEP_V2_HEADER_LEN - 1) & ZEP_LENGTH_MASK);
162 if(ieee_packet_len < tvb_reported_length(tvb)-zep_header_len){
163 /* Packet's length is mis-reported, abort dissection */
164 return 0;
167 col_set_str(pinfo->cinfo, COL_PROTOCOL, (version==1)?"ZEP":"ZEPv2");
169 proto_root = proto_tree_add_item(tree, proto_zep, tvb, 0, zep_header_len, ENC_NA);
170 zep_tree = proto_item_add_subtree(proto_root, ett_zep);
172 proto_tree_add_item(zep_tree, hf_zep_protocol_id, tvb, 0, 2, ENC_NA|ENC_ASCII);
173 proto_tree_add_uint(zep_tree, hf_zep_version, tvb, 2, 1, version);
175 switch (version)
177 case 1:
178 proto_tree_add_item_ret_uint(zep_tree, hf_zep_channel_id, tvb, 3, 1, ENC_NA, &channel_id);
179 col_add_fstr(pinfo->cinfo, COL_INFO, "Encapsulated ZigBee Packet [Channel]=%u [Length]=%u", channel_id, ieee_packet_len);
180 proto_item_append_text(proto_root, ", Channel: %u, Length: %u", channel_id, ieee_packet_len);
182 proto_tree_add_item(zep_tree, hf_zep_device_id, tvb, 4, 2, ENC_BIG_ENDIAN);
183 proto_tree_add_item_ret_boolean(zep_tree, hf_zep_lqi_mode, tvb, 6, 1, ENC_NA, &lqi_mode);
184 if (lqi_mode != 0) {
185 proto_tree_add_item(zep_tree, hf_zep_lqi, tvb, 7, 1, ENC_NA);
186 proto_tree_add_item(zep_tree, hf_zep_reserved_field, tvb, 8, 8, ENC_NA);
187 } else {
188 proto_tree_add_item(zep_tree, hf_zep_reserved_field, tvb, 7, 9, ENC_NA);
191 proto_tree_add_item(zep_tree, hf_zep_ieee_length, tvb, ZEP_V1_HEADER_LEN - 1, 1, ENC_NA);
192 break;
194 case 2:
195 default:
196 proto_tree_add_uint(zep_tree, hf_zep_type, tvb, 3, 1, type);
197 if (type == ZEP_V2_TYPE_ACK) {
198 proto_tree_add_item_ret_uint(zep_tree, hf_zep_seqno, tvb, 4, 4, ENC_BIG_ENDIAN, &seqno);
199 col_add_fstr(pinfo->cinfo, COL_INFO, "Ack, Sequence Number: %i", seqno);
200 proto_item_append_text(proto_root, ", Ack");
201 } else {
202 proto_tree_add_item_ret_uint(zep_tree, hf_zep_channel_id, tvb, 4, 1, ENC_NA, &channel_id);
203 col_add_fstr(pinfo->cinfo, COL_INFO, "Encapsulated ZigBee Packet [Channel]=%u [Length]=%u", channel_id, ieee_packet_len);
204 proto_item_append_text(proto_root, ", Channel: %u, Length: %u", channel_id, ieee_packet_len);
205 proto_tree_add_item(zep_tree, hf_zep_device_id, tvb, 5, 2, ENC_BIG_ENDIAN);
206 proto_tree_add_item_ret_boolean(zep_tree, hf_zep_lqi_mode, tvb, 7, 1, ENC_NA, &lqi_mode);
207 if (lqi_mode == 0) {
208 proto_tree_add_item(zep_tree, hf_zep_lqi, tvb, 8, 1, ENC_NA);
210 proto_tree_add_item(zep_tree, hf_zep_timestamp, tvb, 9, 8, ENC_BIG_ENDIAN|ENC_TIME_NTP);
211 proto_tree_add_item(zep_tree, hf_zep_seqno, tvb, 17, 4, ENC_BIG_ENDIAN);
212 proto_tree_add_item(zep_tree, hf_zep_ieee_length, tvb, ZEP_V2_HEADER_LEN - 1, 1, ENC_NA);
214 break;
217 /* Determine which dissector to call next. */
218 if (lqi_mode) {
219 /* CRC present, use standard IEEE dissector.
220 * XXX - 2-octet or 4-octet CRC?
222 next_dissector = ieee802154_handle;
224 else {
225 /* ChipCon/TI CC24xx-compliant metadata present, CRC absent */
226 next_dissector = ieee802154_cc24xx_handle;
229 /* Call the appropriate IEEE 802.15.4 dissector */
230 if (!((version>=2) && (type==ZEP_V2_TYPE_ACK))) {
231 next_tvb = tvb_new_subset_length(tvb, zep_header_len, ieee_packet_len);
232 if (next_dissector != NULL) {
233 call_dissector(next_dissector, next_tvb, pinfo, tree);
234 } else {
235 /* IEEE 802.15.4 dissectors couldn't be found. */
236 call_data_dissector(next_tvb, pinfo, tree);
239 return tvb_captured_length(tvb);
240 } /* dissect_ieee802_15_4 */
242 /*FUNCTION:------------------------------------------------------
243 * NAME
244 * proto_register_zep
245 * DESCRIPTION
246 * IEEE 802.15.4 protocol registration routine.
247 * PARAMETERS
248 * none
249 * RETURNS
250 * void
251 *---------------------------------------------------------------
253 void proto_register_zep(void)
255 static hf_register_info hf[] = {
256 { &hf_zep_version,
257 { "Protocol Version", "zep.version", FT_UINT8, BASE_DEC, NULL, 0x0,
258 "The version of the sniffer.", HFILL }},
260 { &hf_zep_type,
261 { "Type", "zep.type", FT_UINT8, BASE_DEC|BASE_RANGE_STRING, RVALS(type_rvals), 0x0,
262 NULL, HFILL }},
264 { &hf_zep_channel_id,
265 { "Channel ID", "zep.channel_id", FT_UINT8, BASE_DEC, NULL, 0x0,
266 "The logical channel on which this packet was detected.", HFILL }},
268 { &hf_zep_device_id,
269 { "Device ID", "zep.device_id", FT_UINT16, BASE_DEC, NULL, 0x0,
270 "The ID of the device that detected this packet.", HFILL }},
272 { &hf_zep_lqi_mode,
273 { "LQI/CRC Mode", "zep.lqi_mode", FT_BOOLEAN, BASE_NONE, TFS(&tfs_crc_lqi), 0x0,
274 "Determines what format the last two bytes of the MAC frame use.", HFILL }},
276 { &hf_zep_lqi,
277 { "Link Quality Indication", "zep.lqi", FT_UINT8, BASE_DEC, NULL, 0x0,
278 NULL, HFILL }},
280 { &hf_zep_timestamp,
281 { "Timestamp", "zep.time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
282 NULL, HFILL }},
284 { &hf_zep_seqno,
285 { "Sequence Number", "zep.seqno", FT_UINT32, BASE_DEC, NULL, 0x0,
286 NULL, HFILL }},
288 { &hf_zep_ieee_length,
289 { "Length", "zep.length", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), ZEP_LENGTH_MASK,
290 "The length (in bytes) of the encapsulated IEEE 802.15.4 MAC frame.", HFILL }},
292 { &hf_zep_protocol_id,
293 { "Protocol ID String", "zep.protocol_id", FT_STRING, BASE_NONE, NULL, 0x0,
294 NULL, HFILL }},
296 { &hf_zep_reserved_field,
297 { "Reserved Fields", "zep.reserved_field", FT_BYTES, BASE_NONE, NULL, 0x0,
298 NULL, HFILL }},
301 static int *ett[] = {
302 &ett_zep
305 /* Register protocol name and description. */
306 proto_zep = proto_register_protocol("ZigBee Encapsulation Protocol", "ZEP", "zep");
308 /* Register header fields and subtrees. */
309 proto_register_field_array(proto_zep, hf, array_length(hf));
310 proto_register_subtree_array(ett, array_length(ett));
312 /* Register dissector with Wireshark. */
313 zep_handle = register_dissector("zep", dissect_zep, proto_zep);
314 } /* proto_register_zep */
316 /*FUNCTION:------------------------------------------------------
317 * NAME
318 * proto_reg_handoff_zep
319 * DESCRIPTION
320 * Registers the zigbee dissector with Wireshark.
321 * Will be called every time 'apply' is pressed in the preferences menu.
322 * PARAMETERS
323 * none
324 * RETURNS
325 * void
326 *---------------------------------------------------------------
328 void proto_reg_handoff_zep(void)
330 dissector_handle_t h;
332 /* Get dissector handles. */
333 if ( !(h = find_dissector("wpan")) ) { /* Try use built-in 802.15.4 dissector */
334 h = find_dissector("ieee802154"); /* otherwise use older 802.15.4 plugin dissector */
336 ieee802154_handle = h;
337 if ( !(h = find_dissector("wpan_cc24xx")) ) { /* Try use built-in 802.15.4 (Chipcon) dissector */
338 h = find_dissector("ieee802154_ccfcs"); /* otherwise use older 802.15.4 (Chipcon) plugin dissector */
340 ieee802154_cc24xx_handle = h;
342 dissector_add_uint("udp.port", ZEP_DEFAULT_PORT, zep_handle);
343 } /* proto_reg_handoff_zep */
346 * Editor modelines - https://www.wireshark.org/tools/modelines.html
348 * Local variables:
349 * c-basic-offset: 4
350 * tab-width: 8
351 * indent-tabs-mode: nil
352 * End:
354 * vi: set shiftwidth=4 tabstop=8 expandtab:
355 * :indentSize=4:tabSize=8:noTabs=true: