Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-loratap.c
bloba2ef5e62ca739f489f4a035b9b33f6a4cc4cec3a
1 /* packet-loratap.c
2 * Dissector routines for the LoRaTap encapsulation
3 * By Erik de Jong <erikdejong@gmail.com>
4 * Copyright 2017 Erik de Jong
6 * LoRaTap encapsulation, version 1
7 * By Ales Povalac <alpov@alpov.net>
8 * Copyright 2022 Ales Povalac
9 *
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
14 * SPDX-License-Identifier: GPL-2.0-or-later
17 #include "config.h"
18 #include <epan/packet.h>
19 #include <epan/capture_dissectors.h>
20 #include <epan/decode_as.h>
21 #include <epan/proto_data.h>
22 #include <epan/to_str.h>
23 #include <epan/tfs.h>
24 #include <epan/unit_strings.h>
26 #include <wsutil/array.h>
29 void proto_reg_handoff_loratap(void);
30 void proto_register_loratap(void);
32 static dissector_handle_t loratap_handle;
34 static dissector_table_t loratap_dissector_table;
36 static int proto_loratap;
37 static int hf_loratap_header_version_type;
38 static int hf_loratap_header_length_type;
39 static int hf_loratap_header_padding;
40 static int hf_loratap_header_channel_type;
41 static int hf_loratap_header_channel_frequency_type;
42 static int hf_loratap_header_channel_bandwidth_type;
43 static int hf_loratap_header_channel_sf_type;
44 static int hf_loratap_header_rssi_type;
45 static int hf_loratap_header_rssi_packet_type;
46 static int hf_loratap_header_rssi_max_type;
47 static int hf_loratap_header_rssi_current_type;
48 static int hf_loratap_header_rssi_snr_type;
49 static int hf_loratap_header_syncword_type;
50 static int hf_loratap_header_tag_type;
51 static int hf_loratap_header_payload_type;
52 static int hf_loratap_header_source_gw_type;
53 static int hf_loratap_header_timestamp_type;
54 static int hf_loratap_header_datarate_type;
55 static int hf_loratap_header_if_channel_type;
56 static int hf_loratap_header_rf_chain_type;
57 static int hf_loratap_header_cr_type;
58 static int hf_loratap_header_flags_type;
59 static int hf_loratap_header_flags_mod_fsk_type;
60 static int hf_loratap_header_flags_iq_inverted_type;
61 static int hf_loratap_header_flags_implicit_hdr_type;
62 static int hf_loratap_header_flags_crc_type;
63 static int hf_loratap_header_flags_padding_type;
65 static int * const hfx_loratap_header_flags[] = {
66 &hf_loratap_header_flags_mod_fsk_type,
67 &hf_loratap_header_flags_iq_inverted_type,
68 &hf_loratap_header_flags_implicit_hdr_type,
69 &hf_loratap_header_flags_crc_type,
70 &hf_loratap_header_flags_padding_type,
71 NULL
74 static int ett_loratap;
75 static int ett_loratap_flags;
76 static int ett_loratap_channel;
77 static int ett_loratap_rssi;
79 static const value_string channel_bandwidth[] = {
80 { 1, "125 kHz" },
81 { 2, "250 kHz" },
82 { 4, "500 kHz" },
83 { 0, NULL}
86 static const value_string syncwords[] = {
87 { 0x12, "Private LoRa" },
88 { 0x34, "LoRaWAN" },
89 { 0, NULL}
92 static const value_string coding_rates[] = {
93 { 0, "none" },
94 { 5, "4/5" },
95 { 6, "4/6" },
96 { 7, "4/7" },
97 { 8, "4/8" },
98 { 0, NULL}
101 static const value_string crc_state[] = {
102 { 1, "CRC OK" },
103 { 2, "CRC Bad" },
104 { 4, "No CRC" },
105 { 0, NULL}
108 static void
109 rssi_base_custom(char *buffer, uint32_t value)
111 if (value == 255) {
112 snprintf(buffer, ITEM_LABEL_LENGTH, "N/A");
113 } else {
114 snprintf(buffer, ITEM_LABEL_LENGTH, "%.0f dBm", -139. + (float)value);
118 static void
119 snr_base_custom(char *buffer, uint32_t value)
121 snprintf(buffer, ITEM_LABEL_LENGTH, "%.1f dB", ((int8_t)value) / 4.);
124 static void
125 loratap_prompt(packet_info *pinfo, char* result)
127 snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "LoRaTap syncword 0x%02x as", GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_loratap, 0)));
130 static void *
131 loratap_value(packet_info *pinfo)
133 return p_get_proto_data(pinfo->pool, pinfo, proto_loratap, 0);
136 static int
137 dissect_loratap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, void *data _U_)
139 proto_item *ti, *channel_item, *rssi_item;
140 proto_tree *loratap_tree, *channel_tree, *rssi_tree;
141 int32_t current_offset = 0;
142 int32_t header_v1_offset = 15;
143 uint16_t length;
144 uint32_t lt_length, lt_version;
145 bool try_dissect;
146 uint32_t syncword;
147 tvbuff_t *next_tvb;
149 col_set_str(pinfo->cinfo, COL_PROTOCOL, "LoRaTap");
150 col_clear(pinfo->cinfo, COL_INFO);
151 length = tvb_get_uint16(tvb, 2, ENC_BIG_ENDIAN);
153 ti = proto_tree_add_item(tree, proto_loratap, tvb, 0, length, ENC_NA);
154 loratap_tree = proto_item_add_subtree(ti, ett_loratap);
155 proto_tree_add_item_ret_uint(loratap_tree, hf_loratap_header_version_type, tvb, current_offset, 1, ENC_NA, &lt_version);
156 current_offset++;
157 proto_tree_add_item(loratap_tree, hf_loratap_header_padding, tvb, current_offset, 1, ENC_NA);
158 current_offset++;
159 proto_tree_add_item_ret_uint(loratap_tree, hf_loratap_header_length_type, tvb, current_offset, 2, ENC_NA, &lt_length);
160 current_offset += 2;
161 if (lt_version == 1) {
162 proto_tree_add_item(loratap_tree, hf_loratap_header_source_gw_type, tvb, header_v1_offset, 8, ENC_NA);
163 set_address_tvb(&pinfo->dl_src, AT_EUI64, 8, tvb, header_v1_offset);
164 copy_address_shallow(&pinfo->src, &pinfo->dl_src);
165 proto_item_append_text(ti, ", Src: %s", address_to_display(pinfo->pool, &pinfo->src));
166 header_v1_offset += 8;
167 proto_tree_add_item(loratap_tree, hf_loratap_header_timestamp_type, tvb, header_v1_offset, 4, ENC_NA);
168 header_v1_offset += 4;
169 proto_tree_add_bitmask(loratap_tree, tvb, header_v1_offset, hf_loratap_header_flags_type, ett_loratap_flags, hfx_loratap_header_flags, ENC_NA);
170 try_dissect = (tvb_get_uint8(tvb, header_v1_offset) & 0x28); /* Only try the next dissector for CRC OK and No CRC packets with v1 encapsulation */
171 header_v1_offset++;
172 } else {
173 try_dissect = true; /* Always try the next dissector for v0 encapsulation */
176 channel_item = proto_tree_add_item(loratap_tree, hf_loratap_header_channel_type, tvb, current_offset, 0, ENC_NA);
177 channel_tree = proto_item_add_subtree(channel_item, ett_loratap_channel);
178 proto_tree_add_item(channel_tree, hf_loratap_header_channel_frequency_type, tvb, current_offset, 4, ENC_NA);
179 current_offset += 4;
180 proto_tree_add_item(channel_tree, hf_loratap_header_channel_bandwidth_type, tvb, current_offset, 1, ENC_NA);
181 current_offset++;
182 proto_tree_add_item(channel_tree, hf_loratap_header_channel_sf_type, tvb, current_offset, 1, ENC_NA);
183 current_offset++;
184 if (lt_version == 1) {
185 proto_tree_add_item(channel_tree, hf_loratap_header_cr_type, tvb, header_v1_offset, 1, ENC_NA);
186 header_v1_offset++;
187 proto_tree_add_item(channel_tree, hf_loratap_header_datarate_type, tvb, header_v1_offset, 2, ENC_NA);
188 header_v1_offset += 2;
189 proto_tree_add_item(channel_tree, hf_loratap_header_if_channel_type, tvb, header_v1_offset, 1, ENC_NA);
190 header_v1_offset++;
191 proto_tree_add_item(channel_tree, hf_loratap_header_rf_chain_type, tvb, header_v1_offset, 1, ENC_NA);
192 header_v1_offset++;
195 rssi_item = proto_tree_add_item(loratap_tree, hf_loratap_header_rssi_type, tvb, current_offset, 0, ENC_NA);
196 rssi_tree = proto_item_add_subtree(rssi_item, ett_loratap_rssi);
197 proto_tree_add_item(rssi_tree, hf_loratap_header_rssi_packet_type, tvb, current_offset, 1, ENC_NA);
198 current_offset++;
199 proto_tree_add_item(rssi_tree, hf_loratap_header_rssi_max_type, tvb, current_offset, 1, ENC_NA);
200 current_offset++;
201 proto_tree_add_item(rssi_tree, hf_loratap_header_rssi_current_type, tvb, current_offset, 1, ENC_NA);
202 current_offset++;
203 proto_tree_add_item(rssi_tree, hf_loratap_header_rssi_snr_type, tvb, current_offset, 1, ENC_NA);
204 current_offset++;
205 proto_tree_add_item_ret_uint(loratap_tree, hf_loratap_header_syncword_type, tvb, current_offset, 1, ENC_NA, &syncword);
206 current_offset++;
207 if (lt_version == 1) {
208 proto_tree_add_item(loratap_tree, hf_loratap_header_tag_type, tvb, header_v1_offset, 2, ENC_NA);
211 /* Seek to data - skip lt_length of header, this allows future extensions */
212 current_offset = lt_length;
213 length = tvb_reported_length_remaining(tvb, lt_length);
214 proto_tree_add_bytes_format_value(loratap_tree, hf_loratap_header_payload_type, tvb, current_offset, length, NULL, "%d bytes", length);
216 p_add_proto_data(pinfo->pool, pinfo, proto_loratap, 0, GUINT_TO_POINTER((unsigned)syncword));
217 next_tvb = tvb_new_subset_length(tvb, current_offset, length);
219 if (!try_dissect || !dissector_try_uint_with_data(loratap_dissector_table, syncword, next_tvb, pinfo, tree, true, NULL)) {
220 call_data_dissector(next_tvb, pinfo, tree);
223 return tvb_captured_length(tvb);
226 void
227 proto_reg_handoff_loratap(void)
229 dissector_add_uint("wtap_encap", WTAP_ENCAP_LORATAP, loratap_handle);
230 dissector_add_for_decode_as("udp.port", loratap_handle);
233 void
234 proto_register_loratap(void)
236 static hf_register_info hf[] = {
237 { &hf_loratap_header_version_type,
238 { "Header Version", "loratap.version",
239 FT_UINT8, BASE_DEC,
240 NULL, 0x0,
241 NULL, HFILL }
243 { &hf_loratap_header_length_type,
244 { "Header Length", "loratap.header_length",
245 FT_UINT16, BASE_DEC|BASE_UNIT_STRING,
246 UNS(&units_byte_bytes), 0x0,
247 NULL, HFILL }
249 { &hf_loratap_header_padding,
250 { "Header Padding", "loratap.padding",
251 FT_BYTES, BASE_NONE,
252 NULL, 0x0,
253 NULL, HFILL }
255 { &hf_loratap_header_channel_type,
256 { "Channel", "loratap.channel",
257 FT_NONE, BASE_NONE,
258 NULL, 0x0,
259 NULL, HFILL }
261 { &hf_loratap_header_channel_frequency_type,
262 { "Frequency", "loratap.channel.frequency",
263 FT_UINT32, BASE_DEC|BASE_UNIT_STRING,
264 UNS(&units_hz), 0x0,
265 NULL, HFILL }
267 { &hf_loratap_header_channel_bandwidth_type,
268 { "Bandwidth", "loratap.channel.bandwidth",
269 FT_UINT8, BASE_DEC,
270 VALS(channel_bandwidth), 0x0,
271 NULL, HFILL }
273 { &hf_loratap_header_channel_sf_type,
274 { "Spreading Factor", "loratap.channel.sf",
275 FT_UINT8, BASE_DEC,
276 NULL, 0x0,
277 NULL, HFILL }
279 { &hf_loratap_header_rssi_type,
280 { "RSSI / SNR", "loratap.rssi",
281 FT_NONE, BASE_NONE,
282 NULL, 0x0,
283 NULL, HFILL }
285 { &hf_loratap_header_rssi_packet_type,
286 { "Packet RSSI", "loratap.rssi.packet",
287 FT_UINT8, BASE_CUSTOM,
288 CF_FUNC(rssi_base_custom), 0x0,
289 NULL, HFILL }
291 { &hf_loratap_header_rssi_max_type,
292 { "Max RSSI", "loratap.rssi.max",
293 FT_UINT8, BASE_CUSTOM,
294 CF_FUNC(rssi_base_custom), 0x0,
295 NULL, HFILL }
297 { &hf_loratap_header_rssi_current_type,
298 { "Current RSSI", "loratap.rssi.current",
299 FT_UINT8, BASE_CUSTOM,
300 CF_FUNC(rssi_base_custom), 0x0,
301 NULL, HFILL }
303 { &hf_loratap_header_rssi_snr_type,
304 { "SNR", "loratap.rssi.snr",
305 FT_UINT8, BASE_CUSTOM,
306 CF_FUNC(snr_base_custom), 0x0,
307 NULL, HFILL }
309 { &hf_loratap_header_syncword_type,
310 { "Sync Word", "loratap.syncword",
311 FT_UINT8, BASE_HEX,
312 VALS(syncwords), 0x0,
313 NULL, HFILL }
315 { &hf_loratap_header_tag_type,
316 { "Tag", "loratap.tag",
317 FT_UINT16, BASE_DEC,
318 NULL, 0x0,
319 NULL, HFILL }
321 { &hf_loratap_header_payload_type,
322 { "Payload", "loratap.payload",
323 FT_BYTES, BASE_NONE,
324 NULL, 0x0,
325 NULL, HFILL }
327 { &hf_loratap_header_source_gw_type,
328 { "Source", "loratap.srcgw",
329 FT_BYTES, BASE_NONE,
330 NULL, 0x0,
331 NULL, HFILL }
333 { &hf_loratap_header_timestamp_type,
334 { "Timestamp", "loratap.timestamp",
335 FT_UINT32, BASE_DEC,
336 NULL, 0x0,
337 NULL, HFILL }
339 { &hf_loratap_header_datarate_type,
340 { "FSK datarate", "loratap.channel.datarate",
341 FT_UINT16, BASE_DEC|BASE_UNIT_STRING,
342 UNS(&units_bit_sec), 0x0,
343 NULL, HFILL }
345 { &hf_loratap_header_if_channel_type,
346 { "IF channel", "loratap.channel.if_channel",
347 FT_UINT8, BASE_DEC,
348 NULL, 0x0,
349 NULL, HFILL }
351 { &hf_loratap_header_rf_chain_type,
352 { "RF chain", "loratap.channel.rf_chain",
353 FT_UINT8, BASE_DEC,
354 NULL, 0x0,
355 NULL, HFILL }
357 { &hf_loratap_header_cr_type,
358 { "Coding Rate", "loratap.channel.cr",
359 FT_UINT8, BASE_DEC,
360 VALS(coding_rates), 0x0,
361 NULL, HFILL }
363 { &hf_loratap_header_flags_type,
364 { "Flags", "loratap.flags",
365 FT_UINT8, BASE_HEX,
366 NULL, 0x0,
367 NULL, HFILL }
369 { &hf_loratap_header_flags_mod_fsk_type,
370 { "FSK Modulation", "loratap.flags.mod_fsk",
371 FT_BOOLEAN, 8,
372 TFS(&tfs_set_notset), 0x01,
373 NULL, HFILL }
375 { &hf_loratap_header_flags_iq_inverted_type,
376 { "IQ Inverted", "loratap.flags.iq_inverted",
377 FT_BOOLEAN, 8,
378 TFS(&tfs_set_notset), 0x02,
379 NULL, HFILL }
381 { &hf_loratap_header_flags_implicit_hdr_type,
382 { "Implicit Header", "loratap.flags.implicit_hdr",
383 FT_BOOLEAN, 8,
384 TFS(&tfs_set_notset), 0x04,
385 NULL, HFILL }
387 { &hf_loratap_header_flags_crc_type,
388 { "Checksum", "loratap.flags.crc",
389 FT_UINT8, BASE_HEX,
390 VALS(crc_state), 0x38,
391 NULL, HFILL }
393 { &hf_loratap_header_flags_padding_type,
394 { "Padding", "loratap.flags.padding",
395 FT_UINT8, BASE_DEC,
396 NULL, 0xC0,
397 NULL, HFILL }
401 /* Register for decode as */
402 static build_valid_func loratap_da_build_value[1] = {loratap_value};
403 static decode_as_value_t loratap_da_values = {loratap_prompt, 1, loratap_da_build_value};
404 static decode_as_t loratap_da = {"loratap", "loratap.syncword", 1, 0, &loratap_da_values, NULL, NULL, decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL};
406 /* Setup protocol subtree array */
407 static int *ett[] = {
408 &ett_loratap,
409 &ett_loratap_flags,
410 &ett_loratap_channel,
411 &ett_loratap_rssi
414 proto_loratap = proto_register_protocol (
415 "LoRaTap header", /* name */
416 "LoRaTap", /* short name */
417 "loratap" /* abbrev */
420 loratap_handle = register_dissector("loratap", dissect_loratap, proto_loratap);
421 proto_register_field_array(proto_loratap, hf, array_length(hf));
422 proto_register_subtree_array(ett, array_length(ett));
423 loratap_dissector_table = register_dissector_table("loratap.syncword", "LoRa Syncword", proto_loratap, FT_UINT8, BASE_HEX);
424 register_decode_as(&loratap_da);
428 * Editor modelines - https://www.wireshark.org/tools/modelines.html
430 * Local variables:
431 * c-basic-offset: 8
432 * tab-width: 8
433 * indent-tabs-mode: t
434 * End:
436 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
437 * :indentSize=8:tabSize=8:noTabs=false: