2 * Dissector routines for the LoRaWAN protocol
3 * By Erik de Jong <erikdejong@gmail.com>
4 * Copyright 2017 Erik de Jong
5 * Copyright 2022 Ales Povalac <alpov@alpov.net>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * SPDX-License-Identifier: GPL-2.0-or-later
16 #include <epan/packet.h>
17 #include <epan/expert.h>
18 #include <epan/prefs.h>
20 #include <epan/strutil.h>
21 #include <epan/crc16-tvb.h> /* For CRC verification */
22 #include <epan/unit_strings.h>
24 #include <wsutil/array.h>
25 #include <wsutil/wsgcrypt.h>
27 void proto_reg_handoff_lorawan(void);
28 void proto_register_lorawan(void);
30 static dissector_handle_t lorawan_handle
;
32 static int proto_lorawan
;
33 static int hf_lorawan_msgtype_type
;
34 static int hf_lorawan_mac_header_type
;
35 static int hf_lorawan_mac_header_ftype_type
;
36 static int hf_lorawan_mac_header_rfu_type
;
37 static int hf_lorawan_mac_header_major_type
;
38 static int hf_lorawan_mac_commands_type
;
39 static int hf_lorawan_mac_command_uplink_type
;
40 static int hf_lorawan_mac_command_downlink_type
;
41 static int hf_lorawan_mac_command_down_link_check_ans_type
;
42 static int hf_lorawan_mac_command_down_link_check_ans_margin_type
;
43 static int hf_lorawan_mac_command_down_link_check_ans_gwcnt_type
;
44 static int hf_lorawan_mac_command_down_link_adr_req_datarate_type
;
45 static int hf_lorawan_mac_command_down_link_adr_req_txpower_type
;
46 static int hf_lorawan_mac_command_down_link_adr_req_channel_type
;
47 static int hf_lorawan_mac_command_down_link_adr_req_channel1_type
;
48 static int hf_lorawan_mac_command_down_link_adr_req_channel2_type
;
49 static int hf_lorawan_mac_command_down_link_adr_req_channel3_type
;
50 static int hf_lorawan_mac_command_down_link_adr_req_channel4_type
;
51 static int hf_lorawan_mac_command_down_link_adr_req_channel5_type
;
52 static int hf_lorawan_mac_command_down_link_adr_req_channel6_type
;
53 static int hf_lorawan_mac_command_down_link_adr_req_channel7_type
;
54 static int hf_lorawan_mac_command_down_link_adr_req_channel8_type
;
55 static int hf_lorawan_mac_command_down_link_adr_req_channel9_type
;
56 static int hf_lorawan_mac_command_down_link_adr_req_channel10_type
;
57 static int hf_lorawan_mac_command_down_link_adr_req_channel11_type
;
58 static int hf_lorawan_mac_command_down_link_adr_req_channel12_type
;
59 static int hf_lorawan_mac_command_down_link_adr_req_channel13_type
;
60 static int hf_lorawan_mac_command_down_link_adr_req_channel14_type
;
61 static int hf_lorawan_mac_command_down_link_adr_req_channel15_type
;
62 static int hf_lorawan_mac_command_down_link_adr_req_channel16_type
;
63 static int hf_lorawan_mac_command_down_link_adr_req_channel_mask_control_type
;
64 static int hf_lorawan_mac_command_down_link_adr_req_repetitions_type
;
65 static int hf_lorawan_mac_command_up_link_adr_ans_txpower_type
;
66 static int hf_lorawan_mac_command_up_link_adr_ans_datarate_type
;
67 static int hf_lorawan_mac_command_up_link_adr_ans_channel_mask_type
;
68 static int hf_lorawan_mac_command_down_dutycycle_type
;
69 static int hf_lorawan_mac_command_down_rx_setup_req_rx1droffset_type
;
70 static int hf_lorawan_mac_command_down_rx_setup_req_rx2datarate_type
;
71 static int hf_lorawan_mac_command_down_rx_setup_req_frequency_type
;
72 static int hf_lorawan_mac_command_up_rx_setup_ans_type
;
73 static int hf_lorawan_mac_command_up_rx_setup_ans_rx1droffset_type
;
74 static int hf_lorawan_mac_command_up_rx_setup_ans_rx2datarate_type
;
75 static int hf_lorawan_mac_command_up_rx_setup_ans_frequency_type
;
76 static int hf_lorawan_mac_command_up_device_status_ans_battery_type
;
77 static int hf_lorawan_mac_command_up_device_status_ans_margin_type
;
78 static int hf_lorawan_mac_command_down_new_channel_req_index_type
;
79 static int hf_lorawan_mac_command_down_new_channel_req_frequency_type
;
80 static int hf_lorawan_mac_command_down_new_channel_req_drrange_max_type
;
81 static int hf_lorawan_mac_command_down_new_channel_req_drrange_min_type
;
82 static int hf_lorawan_mac_command_up_new_channel_ans_type
;
83 static int hf_lorawan_mac_command_up_new_channel_ans_datarate_type
;
84 static int hf_lorawan_mac_command_up_new_channel_ans_frequency_type
;
85 static int hf_lorawan_mac_command_down_rx_timing_req_delay_type
;
86 static int hf_lorawan_mac_command_up_di_channel_ans_type
;
87 static int hf_lorawan_mac_command_up_ping_slot_info_req_type
;
88 static int hf_lorawan_mac_command_up_ping_slot_channel_ans_type
;
89 static int hf_lorawan_mac_command_up_beacon_freq_ans_type
;
90 static int hf_lorawan_mac_command_down_tx_param_setup_req_type
;
91 static int hf_lorawan_mac_command_down_di_channel_req_type
;
92 static int hf_lorawan_mac_command_down_device_time_ans_type
;
93 static int hf_lorawan_mac_command_down_ping_slot_channel_req_type
;
94 static int hf_lorawan_mac_command_down_beacon_freq_req_type
;
95 static int hf_lorawan_join_request_type
;
96 static int hf_lorawan_join_request_joineui_type
;
97 static int hf_lorawan_join_request_deveui_type
;
98 static int hf_lorawan_join_request_devnonce_type
;
99 static int hf_lorawan_join_accept_type
;
100 static int hf_lorawan_join_accept_joinnonce_type
;
101 static int hf_lorawan_join_accept_netid_type
;
102 static int hf_lorawan_join_accept_devaddr_type
;
103 static int hf_lorawan_join_accept_dlsettings_type
;
104 static int hf_lorawan_join_accept_dlsettings_rx1droffset_type
;
105 static int hf_lorawan_join_accept_dlsettings_rx2dr_type
;
106 static int hf_lorawan_join_accept_rxdelay_type
;
107 static int hf_lorawan_join_accept_cflist_type
;
108 static int hf_lorawan_frame_header_type
;
109 static int hf_lorawan_frame_header_address_type
;
110 static int hf_lorawan_frame_header_frame_control_adr_type
;
111 static int hf_lorawan_frame_header_frame_control_adrackreq_type
;
112 static int hf_lorawan_frame_header_frame_control_ack_type
;
113 static int hf_lorawan_frame_header_frame_control_fpending_type
;
114 static int hf_lorawan_frame_header_frame_control_foptslen_type
;
115 static int hf_lorawan_frame_header_frame_control_type
;
116 static int hf_lorawan_frame_header_frame_counter_type
;
117 static int hf_lorawan_frame_fport_type
;
118 static int hf_lorawan_frame_payload_type
;
119 static int hf_lorawan_frame_payload_decrypted_type
;
120 static int hf_lorawan_mic_type
;
121 static int hf_lorawan_mic_status_type
;
122 static int hf_lorawan_beacon_rfu1_type
;
123 static int hf_lorawan_beacon_time_type
;
124 static int hf_lorawan_beacon_crc1_type
;
125 static int hf_lorawan_beacon_crc1_status_type
;
126 static int hf_lorawan_beacon_gwspecific_type
;
127 static int hf_lorawan_beacon_gwspecific_infodesc_type
;
128 static int hf_lorawan_beacon_gwspecific_lat_type
;
129 static int hf_lorawan_beacon_gwspecific_lng_type
;
130 static int hf_lorawan_beacon_rfu2_type
;
131 static int hf_lorawan_beacon_crc2_type
;
132 static int hf_lorawan_beacon_crc2_status_type
;
134 static int * const hfx_lorawan_mac_command_link_check_ans
[] = {
135 &hf_lorawan_mac_command_up_link_adr_ans_txpower_type
,
136 &hf_lorawan_mac_command_up_link_adr_ans_datarate_type
,
137 &hf_lorawan_mac_command_up_link_adr_ans_channel_mask_type
,
140 static int * const hfx_lorawan_mac_command_link_adr_req_channel
[] = {
141 &hf_lorawan_mac_command_down_link_adr_req_channel1_type
,
142 &hf_lorawan_mac_command_down_link_adr_req_channel2_type
,
143 &hf_lorawan_mac_command_down_link_adr_req_channel3_type
,
144 &hf_lorawan_mac_command_down_link_adr_req_channel4_type
,
145 &hf_lorawan_mac_command_down_link_adr_req_channel5_type
,
146 &hf_lorawan_mac_command_down_link_adr_req_channel6_type
,
147 &hf_lorawan_mac_command_down_link_adr_req_channel7_type
,
148 &hf_lorawan_mac_command_down_link_adr_req_channel8_type
,
149 &hf_lorawan_mac_command_down_link_adr_req_channel9_type
,
150 &hf_lorawan_mac_command_down_link_adr_req_channel10_type
,
151 &hf_lorawan_mac_command_down_link_adr_req_channel11_type
,
152 &hf_lorawan_mac_command_down_link_adr_req_channel12_type
,
153 &hf_lorawan_mac_command_down_link_adr_req_channel13_type
,
154 &hf_lorawan_mac_command_down_link_adr_req_channel14_type
,
155 &hf_lorawan_mac_command_down_link_adr_req_channel15_type
,
156 &hf_lorawan_mac_command_down_link_adr_req_channel16_type
,
159 static int * const hfx_lorawan_mac_command_rx_setup_ans
[] = {
160 &hf_lorawan_mac_command_up_rx_setup_ans_rx1droffset_type
,
161 &hf_lorawan_mac_command_up_rx_setup_ans_rx2datarate_type
,
162 &hf_lorawan_mac_command_up_rx_setup_ans_frequency_type
,
165 static int * const hfx_lorawan_mac_command_new_channel_ans
[] = {
166 &hf_lorawan_mac_command_up_new_channel_ans_datarate_type
,
167 &hf_lorawan_mac_command_up_new_channel_ans_frequency_type
,
171 static int * const hfx_lorawan_frame_header_frame_control
[] = {
172 &hf_lorawan_frame_header_frame_control_adr_type
,
173 &hf_lorawan_frame_header_frame_control_adrackreq_type
,
174 &hf_lorawan_frame_header_frame_control_ack_type
,
175 &hf_lorawan_frame_header_frame_control_fpending_type
,
176 &hf_lorawan_frame_header_frame_control_foptslen_type
,
180 static int * const hfx_lorawan_join_accept_dlsettings
[] = {
181 &hf_lorawan_join_accept_dlsettings_rx1droffset_type
,
182 &hf_lorawan_join_accept_dlsettings_rx2dr_type
,
186 static int ett_lorawan
;
187 static int ett_lorawan_mac_header
;
188 static int ett_lorawan_mac_commands
;
189 static int ett_lorawan_mac_command
;
190 static int ett_lorawan_mac_command_link_check_ans
;
191 static int ett_lorawan_mac_command_link_adr_req_channel
;
192 static int ett_lorawan_mac_command_rx_setup_ans
;
193 static int ett_lorawan_mac_command_new_channel_ans
;
194 static int ett_lorawan_join_request
;
195 static int ett_lorawan_join_accept
;
196 static int ett_lorawan_join_accept_dlsettings
;
197 static int ett_lorawan_frame_header
;
198 static int ett_lorawan_frame_header_control
;
199 static int ett_lorawan_frame_payload_decrypted
;
200 static int ett_lorawan_beacon
;
201 static int ett_lorawan_beacon_gwspecific
;
203 #define LORAWAN_MAC_FTYPE_MASK 0xE0
204 #define LORAWAN_MAC_FTYPE(ftype) (((ftype) & LORAWAN_MAC_FTYPE_MASK) >> 5)
206 #define LORAWAN_MAC_FTYPE_JOINREQUEST 0
207 #define LORAWAN_MAC_FTYPE_JOINACCEPT 1
208 #define LORAWAN_MAC_FTYPE_UNCONFIRMEDDATAUP 2
209 #define LORAWAN_MAC_FTYPE_UNCONFIRMEDDATADOWN 3
210 #define LORAWAN_MAC_FTYPE_CONFIRMEDDATAUP 4
211 #define LORAWAN_MAC_FTYPE_CONFIRMEDDATADOWN 5
212 #define LORAWAN_MAC_FTYPE_RFU 6
213 #define LORAWAN_MAC_FTYPE_PROPRIETARY 7
214 #define LORAWAN_MAC_BEACON 0xFFF0
216 #define LORAWAN_MAC_RFU_MASK 0x1C
218 #define LORAWAN_MAC_MAJOR_MASK 0x03
219 #define LORAWAN_MAC_MAJOR(major) ((major) & LORAWAN_MAC_MAJOR_MASK)
221 #define LORAWAN_MAC_MAJOR_R1 0
223 #define LORAWAN_MAC_COMMAND_UP_LINK_CHECK_REQ 0x02
224 #define LORAWAN_MAC_COMMAND_UP_LINK_ADR_ANS 0x03
225 #define LORAWAN_MAC_COMMAND_UP_DUTY_ANS 0x04
226 #define LORAWAN_MAC_COMMAND_UP_RX_SETUP_ANS 0x05
227 #define LORAWAN_MAC_COMMAND_UP_DEV_STATUS_ANS 0x06
228 #define LORAWAN_MAC_COMMAND_UP_NEW_CHANNEL_ANS 0x07
229 #define LORAWAN_MAC_COMMAND_UP_RX_TIMING_ANS 0x08
230 #define LORAWAN_MAC_COMMAND_UP_TX_PARAM_SETUP_ANS 0x09
231 #define LORAWAN_MAC_COMMAND_UP_DI_CHANNEL_ANS 0x0A
232 #define LORAWAN_MAC_COMMAND_UP_DEVICE_TIME_REQ 0x0D
233 #define LORAWAN_MAC_COMMAND_UP_PING_SLOT_INFO_REQ 0x10
234 #define LORAWAN_MAC_COMMAND_UP_PING_SLOT_CHANNEL_ANS 0x11
235 #define LORAWAN_MAC_COMMAND_UP_BEACON_TIMING_REQ 0x12
236 #define LORAWAN_MAC_COMMAND_UP_BEACON_FREQ_ANS 0x13
238 #define LORAWAN_MAC_COMMAND_DOWN_LINK_CHECK_ANS 0x02
239 #define LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ 0x03
240 #define LORAWAN_MAC_COMMAND_DOWN_DUTY_REQ 0x04
241 #define LORAWAN_MAC_COMMAND_DOWN_RX_SETUP_REQ 0x05
242 #define LORAWAN_MAC_COMMAND_DOWN_DEV_STATUS_REQ 0x06
243 #define LORAWAN_MAC_COMMAND_DOWN_NEW_CHANNEL_REQ 0x07
244 #define LORAWAN_MAC_COMMAND_DOWN_RX_TIMING_REQ 0x08
245 #define LORAWAN_MAC_COMMAND_DOWN_TX_PARAM_SETUP_REQ 0x09
246 #define LORAWAN_MAC_COMMAND_DOWN_DI_CHANNEL_REQ 0x0A
247 #define LORAWAN_MAC_COMMAND_DOWN_DEVICE_TIME_ANS 0x0D
248 #define LORAWAN_MAC_COMMAND_DOWN_PING_SLOT_INFO_ANS 0x10
249 #define LORAWAN_MAC_COMMAND_DOWN_PING_SLOT_CHANNEL_REQ 0x11
250 #define LORAWAN_MAC_COMMAND_DOWN_BEACON_TIMING_ANS 0x12
251 #define LORAWAN_MAC_COMMAND_DOWN_BEACON_FREQ_REQ 0x13
253 #define LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_DATARATE_MASK 0xF0
254 #define LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_TXPOWER_MASK 0x0F
255 #define LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_1_MASK 0x0001
256 #define LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_2_MASK 0x0002
257 #define LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_3_MASK 0x0004
258 #define LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_4_MASK 0x0008
259 #define LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_5_MASK 0x0010
260 #define LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_6_MASK 0x0020
261 #define LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_7_MASK 0x0040
262 #define LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_8_MASK 0x0080
263 #define LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_9_MASK 0x0100
264 #define LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_10_MASK 0x0200
265 #define LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_11_MASK 0x0400
266 #define LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_12_MASK 0x0800
267 #define LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_13_MASK 0x1000
268 #define LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_14_MASK 0x2000
269 #define LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_15_MASK 0x4000
270 #define LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_16_MASK 0x8000
271 #define LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHMASKCNTL_MASK 0x70
272 #define LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_NBREP_MASK 0x0F
273 #define LORAWAN_MAC_COMMAND_UP_LINK_ADR_ANS_TXPOWER_MASK 0x04
274 #define LORAWAN_MAC_COMMAND_UP_LINK_ADR_ANS_DATARATE_MASK 0x02
275 #define LORAWAN_MAC_COMMAND_UP_LINK_ADR_ANS_CHANNEL_MASK 0x01
276 #define LORAWAN_MAC_COMMAND_DOWN_RX_SETUP_RX1DROFFSET_MASK 0x70
277 #define LORAWAN_MAC_COMMAND_DOWN_RX_SETUP_RX2DATARATE_MASK 0x0F
278 #define LORAWAN_MAC_COMMAND_UP_RX_SETUP_ANS_TXPOWER_MASK 0x04
279 #define LORAWAN_MAC_COMMAND_UP_RX_SETUP_ANS_DATARATE_MASK 0x02
280 #define LORAWAN_MAC_COMMAND_UP_RX_SETUP_ANS_CHANNEL_MASK 0x01
281 #define LORAWAN_MAC_COMMAND_UP_DEVICE_STATUS_ANS_MARGIN_MASK 0x3F
282 #define LORAWAN_MAC_COMMAND_DOWN_NEW_CHANNEL_REQ_DRRANGE_MAX_MASK 0xF0
283 #define LORAWAN_MAC_COMMAND_DOWN_NEW_CHANNEL_REQ_DRRANGE_MIN_MASK 0x0F
284 #define LORAWAN_MAC_COMMAND_UP_NEW_CHANNEL_ANS_DATARATE_MASK 0x02
285 #define LORAWAN_MAC_COMMAND_UP_NEW_CHANNEL_ANS_FREQUENCY_MASK 0x01
286 #define LORAWAN_MAC_COMMAND_DOWN_RX_TIMING_REQ_DELAY_MASK 0x0F
288 #define LORAWAN_JOIN_ACCEPT_RX1DROFFSET_MASK 0x70
289 #define LORAWAN_JOIN_ACCEPT_RX2DR_MASK 0x0F
291 #define LORAWAN_FRAME_FOPTSLEN_MASK 0x0F
293 #define LORAWAN_AES_BLOCK_LENGTH 16
294 #define LORAWAN_AES_PADDEDSIZE(length) (LORAWAN_AES_BLOCK_LENGTH * ((length + LORAWAN_AES_BLOCK_LENGTH - 1) / LORAWAN_AES_BLOCK_LENGTH))
296 static expert_field ei_lorawan_missing_keys
;
297 static expert_field ei_lorawan_decrypting_error
;
298 static expert_field ei_lorawan_mic
;
299 static expert_field ei_lorawan_length_error
;
300 static expert_field ei_lorawan_mhdr_error
;
302 static const value_string lorawan_ftypenames
[] = {
303 { LORAWAN_MAC_FTYPE_JOINREQUEST
, "Join Request" },
304 { LORAWAN_MAC_FTYPE_JOINACCEPT
, "Join Accept" },
305 { LORAWAN_MAC_FTYPE_UNCONFIRMEDDATAUP
, "Unconfirmed Data Up" },
306 { LORAWAN_MAC_FTYPE_UNCONFIRMEDDATADOWN
, "Unconfirmed Data Down" },
307 { LORAWAN_MAC_FTYPE_CONFIRMEDDATAUP
, "Confirmed Data Up" },
308 { LORAWAN_MAC_FTYPE_CONFIRMEDDATADOWN
, "Confirmed Data Down" },
309 { LORAWAN_MAC_FTYPE_RFU
, "RFU" },
310 { LORAWAN_MAC_FTYPE_PROPRIETARY
, "Proprietary" },
311 // TODO: having this here makes no sense.
312 // It's value doesn't fit into 3 bits, and is only ever looked up with a hardcoded key...
313 { LORAWAN_MAC_BEACON
, "Class-B Beacon" },
317 static const value_string lorawan_majornames
[] = {
318 { LORAWAN_MAC_MAJOR_R1
, "LoRaWAN R1" },
322 static const value_string lorawan_mac_uplink_commandnames
[] = {
323 { LORAWAN_MAC_COMMAND_UP_LINK_CHECK_REQ
, "Network validation request" },
324 { LORAWAN_MAC_COMMAND_UP_LINK_ADR_ANS
, "Data rate adjustment response" },
325 { LORAWAN_MAC_COMMAND_UP_DUTY_ANS
, "Duty-cycle rate set response" },
326 { LORAWAN_MAC_COMMAND_UP_RX_SETUP_ANS
, "Reception slots set response" },
327 { LORAWAN_MAC_COMMAND_UP_DEV_STATUS_ANS
, "Status response" },
328 { LORAWAN_MAC_COMMAND_UP_NEW_CHANNEL_ANS
, "Channel creation/modification response" },
329 { LORAWAN_MAC_COMMAND_UP_RX_TIMING_ANS
, "Reception slots timing set response" },
330 { LORAWAN_MAC_COMMAND_UP_TX_PARAM_SETUP_ANS
, "End-device transmit parameters response" },
331 { LORAWAN_MAC_COMMAND_UP_DI_CHANNEL_ANS
, "Channel DI response" },
332 { LORAWAN_MAC_COMMAND_UP_DEVICE_TIME_REQ
, "End-device time request" },
333 { LORAWAN_MAC_COMMAND_UP_PING_SLOT_INFO_REQ
, "Class-B ping-slot periodicity request" },
334 { LORAWAN_MAC_COMMAND_UP_PING_SLOT_CHANNEL_ANS
, "Class-B ping-slot frequency response" },
335 { LORAWAN_MAC_COMMAND_UP_BEACON_TIMING_REQ
, "Class-B beacon timing request" },
336 { LORAWAN_MAC_COMMAND_UP_BEACON_FREQ_ANS
, "Class-B beacon frequency response" },
340 static const value_string lorawan_mac_downlink_commandnames
[] = {
341 { LORAWAN_MAC_COMMAND_DOWN_LINK_CHECK_ANS
, "Network validation response" },
342 { LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ
, "Data rate adjustment request" },
343 { LORAWAN_MAC_COMMAND_DOWN_DUTY_REQ
, "Duty-cycle rate set request" },
344 { LORAWAN_MAC_COMMAND_DOWN_RX_SETUP_REQ
, "Reception slots set request" },
345 { LORAWAN_MAC_COMMAND_DOWN_DEV_STATUS_REQ
, "Status request" },
346 { LORAWAN_MAC_COMMAND_DOWN_NEW_CHANNEL_REQ
, "Channel creation/modification request" },
347 { LORAWAN_MAC_COMMAND_DOWN_RX_TIMING_REQ
, "Reception slots timing set request" },
348 { LORAWAN_MAC_COMMAND_DOWN_TX_PARAM_SETUP_REQ
, "End-device transmit parameters request" },
349 { LORAWAN_MAC_COMMAND_DOWN_DI_CHANNEL_REQ
, "Channel DI request" },
350 { LORAWAN_MAC_COMMAND_DOWN_DEVICE_TIME_ANS
, "End-device time response" },
351 { LORAWAN_MAC_COMMAND_DOWN_PING_SLOT_INFO_ANS
, "Class-B ping-slot periodicity response" },
352 { LORAWAN_MAC_COMMAND_DOWN_PING_SLOT_CHANNEL_REQ
, "Class-B ping-slot frequency request" },
353 { LORAWAN_MAC_COMMAND_DOWN_BEACON_TIMING_ANS
, "Class-B beacon timing response" },
354 { LORAWAN_MAC_COMMAND_DOWN_BEACON_FREQ_REQ
, "Class-B beacon frequency request" },
359 typedef struct _root_keys_t
{
366 typedef struct _session_keys_t
{
367 char *dev_addr_string
;
368 char *nwkskey_string
;
369 char *appskey_string
;
375 static root_key_t
*root_keys
;
376 static session_key_t
*session_keys
;
377 static unsigned root_num_keys
;
378 static unsigned session_num_keys
;
381 byte_array_reverse(GByteArray
*arr
)
383 for (unsigned i
= 0; i
< arr
->len
/ 2; i
++) {
384 int8_t b
= arr
->data
[i
];
385 arr
->data
[i
] = arr
->data
[(arr
->len
- 1) - i
];
386 arr
->data
[(arr
->len
- 1) - i
] = b
;
391 root_keys_update_cb(void *r
, char **err
)
393 root_key_t
*rec
= (root_key_t
*)r
;
395 if (rec
->deveui_string
== NULL
) {
396 *err
= g_strdup("End-device identifier can't be empty");
400 rec
->deveui
= g_byte_array_new();
402 if (!hex_str_to_bytes(rec
->deveui_string
, rec
->deveui
, false)) {
403 *err
= g_strdup("End-device identifier must be hexadecimal");
406 if (rec
->deveui
->len
!= 8) {
407 *err
= g_strdup("End-device identifier must be 8 bytes hexadecimal");
410 byte_array_reverse(rec
->deveui
);
412 if (rec
->appkey_string
== NULL
) {
413 *err
= g_strdup("Application key can't be empty");
417 rec
->appkey
= g_byte_array_new();
419 if (!hex_str_to_bytes(rec
->appkey_string
, rec
->appkey
, false)) {
420 *err
= g_strdup("Application key must be hexadecimal");
423 if (rec
->appkey
->len
!= 16) {
424 *err
= g_strdup("Application key must be 16 bytes hexadecimal");
433 root_keys_copy_cb(void *n
, const void *o
, size_t siz _U_
)
435 root_key_t
*new_rec
= (root_key_t
*)n
;
436 const root_key_t
*old_rec
= (const root_key_t
*)o
;
438 if (old_rec
->deveui_string
) {
439 new_rec
->deveui_string
= g_strdup(old_rec
->deveui_string
);
440 new_rec
->deveui
= g_byte_array_new();
441 hex_str_to_bytes(new_rec
->deveui_string
, new_rec
->deveui
, false);
442 byte_array_reverse(new_rec
->deveui
);
444 new_rec
->deveui_string
= NULL
;
445 new_rec
->deveui
= NULL
;
448 if (old_rec
->appkey_string
) {
449 new_rec
->appkey_string
= g_strdup(old_rec
->appkey_string
);
450 new_rec
->appkey
= g_byte_array_new();
451 hex_str_to_bytes(new_rec
->appkey_string
, new_rec
->appkey
, false);
454 new_rec
->appkey_string
= NULL
;
455 new_rec
->appkey
= NULL
;
462 root_keys_free_cb(void *r
)
464 root_key_t
*rec
= (root_key_t
*)r
;
466 g_free(rec
->deveui_string
);
467 g_byte_array_free(rec
->deveui
, true);
468 g_free(rec
->appkey_string
);
469 g_byte_array_free(rec
->appkey
, true);
473 session_keys_update_cb(void *r
, char **err
)
475 session_key_t
*rec
= (session_key_t
*)r
;
477 if (rec
->dev_addr_string
== NULL
) {
478 *err
= g_strdup("Device address can't be empty");
481 GByteArray
*addr
= g_byte_array_new();
482 if (!hex_str_to_bytes(rec
->dev_addr_string
, addr
, false)) {
483 g_byte_array_free(addr
, true);
484 *err
= g_strdup("Device address must be hexadecimal");
487 if (addr
->len
!= 4) {
488 g_byte_array_free(addr
, true);
489 *err
= g_strdup("Device address must be 4 bytes hexadecimal");
492 byte_array_reverse(addr
);
493 memcpy(&rec
->dev_addr
, addr
->data
, sizeof(rec
->dev_addr
));
494 g_byte_array_free(addr
, true);
496 if (rec
->nwkskey_string
== NULL
) {
497 *err
= g_strdup("Network session key can't be empty");
501 rec
->nwkskey
= g_byte_array_new();
503 if (!hex_str_to_bytes(rec
->nwkskey_string
, rec
->nwkskey
, false)) {
504 *err
= g_strdup("Network session key must be hexadecimal");
507 if (rec
->nwkskey
->len
!= 16) {
508 *err
= g_strdup("Network session key must be 16 bytes hexadecimal");
512 if (rec
->appskey_string
== NULL
) {
513 *err
= g_strdup("Application session key can't be empty");
517 rec
->appskey
= g_byte_array_new();
519 if (!hex_str_to_bytes(rec
->appskey_string
, rec
->appskey
, false)) {
520 *err
= g_strdup("Application session key must be hexadecimal");
523 if (rec
->appskey
->len
!= 16) {
524 *err
= g_strdup("Application session key must be 16 bytes hexadecimal");
533 session_keys_copy_cb(void *n
, const void *o
, size_t siz _U_
)
535 session_key_t
*new_rec
= (session_key_t
*)n
;
536 const session_key_t
*old_rec
= (const session_key_t
*)o
;
538 if (old_rec
->dev_addr_string
) {
539 new_rec
->dev_addr_string
= g_strdup(old_rec
->dev_addr_string
);
540 GByteArray
*addr
= g_byte_array_new();
541 if (hex_str_to_bytes(new_rec
->dev_addr_string
, addr
, false)) {
542 if (addr
->len
== 4) {
543 byte_array_reverse(addr
);
544 memcpy(&new_rec
->dev_addr
, addr
->data
, sizeof(new_rec
->dev_addr
));
546 new_rec
->dev_addr
= 0;
549 g_byte_array_free(addr
, true);
551 new_rec
->dev_addr_string
= NULL
;
552 new_rec
->dev_addr
= 0;
555 if (old_rec
->nwkskey_string
) {
556 new_rec
->nwkskey_string
= g_strdup(old_rec
->nwkskey_string
);
557 new_rec
->nwkskey
= g_byte_array_new();
558 hex_str_to_bytes(new_rec
->nwkskey_string
, new_rec
->nwkskey
, false);
560 new_rec
->nwkskey_string
= NULL
;
561 new_rec
->nwkskey
= NULL
;
564 if (old_rec
->appskey_string
) {
565 new_rec
->appskey_string
= g_strdup(old_rec
->appskey_string
);
566 new_rec
->appskey
= g_byte_array_new();
567 hex_str_to_bytes(new_rec
->appskey_string
, new_rec
->appskey
, false);
569 new_rec
->appskey_string
= NULL
;
570 new_rec
->appskey
= NULL
;
577 session_keys_free_cb(void *r
)
579 session_key_t
*rec
= (session_key_t
*)r
;
581 g_free(rec
->dev_addr_string
);
582 g_free(rec
->nwkskey_string
);
583 g_byte_array_free(rec
->nwkskey
, true);
584 g_free(rec
->appskey_string
);
585 g_byte_array_free(rec
->appskey
, true);
588 UAT_CSTRING_CB_DEF(root_keys
, deveui_string
, root_key_t
)
589 UAT_CSTRING_CB_DEF(root_keys
, appkey_string
, root_key_t
)
590 UAT_CSTRING_CB_DEF(session_keys
, dev_addr_string
, session_key_t
)
591 UAT_CSTRING_CB_DEF(session_keys
, nwkskey_string
, session_key_t
)
592 UAT_CSTRING_CB_DEF(session_keys
, appskey_string
, session_key_t
)
594 static session_key_t
*
595 get_session_key(uint32_t dev_addr
)
598 for (i
= 0; i
< session_num_keys
; i
++) {
599 if (session_keys
[i
].dev_addr
== dev_addr
) {
600 return &session_keys
[i
];
607 get_root_key(const uint8_t *deveui
)
610 for (i
= 0; i
< root_num_keys
; i
++) {
611 if (root_keys
[i
].deveui
!= NULL
&& memcmp(root_keys
[i
].deveui
->data
, deveui
, 8) == 0) {
612 return &root_keys
[i
];
619 calculate_mic(const uint8_t *in
, uint8_t length
, const uint8_t *key
)
622 * cmac = aes128_cmac(key, in)
625 gcry_mac_hd_t mac_hd
;
627 size_t read_digest_length
= 4;
629 if (gcry_mac_open(&mac_hd
, GCRY_MAC_CMAC_AES
, 0, NULL
)) {
632 if (gcry_mac_setkey(mac_hd
, key
, 16)) {
633 gcry_mac_close(mac_hd
);
636 /* Pass in the message */
637 if (gcry_mac_write(mac_hd
, in
, length
)) {
638 gcry_mac_close(mac_hd
);
641 /* Read out the digest */
642 if (gcry_mac_read(mac_hd
, &mac
, &read_digest_length
)) {
643 gcry_mac_close(mac_hd
);
646 /* Now close the mac handle */
647 gcry_mac_close(mac_hd
);
652 gps_to_utctime(const uint32_t gpstime
)
655 utctime
.secs
= (uint64_t)gpstime
;
656 utctime
.secs
+= 315964800; /* difference between Unix epoch and GPS epoch */
657 utctime
.secs
-= 18; /* leap seconds valid after 2017-01-01 */
663 cf_coords_lat_custom(char *buffer
, uint32_t value
)
665 int32_t coord_int
= (value
< 0x00800000) ? ((int32_t)value
) : ((int32_t)value
- 0x01000000);
666 double coord_double
= coord_int
* 90. / 0x00800000;
668 snprintf(buffer
, ITEM_LABEL_LENGTH
, "%.5f%c", fabs(coord_double
), (coord_double
>= 0) ? 'N' : 'S');
672 cf_coords_lng_custom(char *buffer
, uint32_t value
)
674 int32_t coord_int
= (value
< 0x00800000) ? ((int32_t)value
) : ((int32_t)value
- 0x01000000);
675 double coord_double
= coord_int
* 180. / 0x00800000;
677 snprintf(buffer
, ITEM_LABEL_LENGTH
, "%.5f%c", fabs(coord_double
), (coord_double
>= 0) ? 'E' : 'W');
681 aes128_lorawan_encrypt(const uint8_t *key
, const uint8_t *data_in
, uint8_t *data_out
, int length
)
683 gcry_cipher_hd_t cipher
;
684 if (gcry_cipher_open(&cipher
, GCRY_CIPHER_AES128
, GCRY_CIPHER_MODE_ECB
, 0)) {
687 if (gcry_cipher_setkey(cipher
, key
, LORAWAN_AES_BLOCK_LENGTH
)) {
688 gcry_cipher_close(cipher
);
691 if (gcry_cipher_encrypt(cipher
, data_out
, length
, data_in
, length
)) {
692 gcry_cipher_close(cipher
);
695 gcry_cipher_close(cipher
);
699 /* length should be a multiple of 16, in should be padded to get to a multiple of 16 */
701 decrypt_lorawan_frame_payload(const uint8_t *in
, int length
, uint8_t *out
, const uint8_t * key
, uint8_t dir
, uint32_t dev_addr
, uint32_t fcnt
)
703 gcry_cipher_hd_t cipher
;
704 uint8_t iv
[LORAWAN_AES_BLOCK_LENGTH
] = {0x01, 0x00, 0x00, 0x00, 0x00, dir
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
705 memcpy(iv
+ 6, &dev_addr
, 4);
706 memcpy(iv
+ 10, &fcnt
, 4);
707 if (gcry_cipher_open(&cipher
, GCRY_CIPHER_AES128
, GCRY_CIPHER_MODE_CTR
, 0)) {
710 if (gcry_cipher_setkey(cipher
, key
, LORAWAN_AES_BLOCK_LENGTH
)) {
711 gcry_cipher_close(cipher
);
714 if (gcry_cipher_setctr(cipher
, iv
, 16)) {
715 gcry_cipher_close(cipher
);
718 if (gcry_cipher_encrypt(cipher
, out
, length
, in
, length
)) {
719 gcry_cipher_close(cipher
);
722 gcry_cipher_close(cipher
);
727 dissect_lorawan_mac_commands(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree _U_
, bool uplink
)
730 proto_tree
*mac_command_tree
, *field_tree
;
732 int32_t current_offset
= 0;
734 ti
= proto_tree_add_item(tree
, hf_lorawan_mac_commands_type
, tvb
, 0, -1, ENC_NA
);
735 mac_command_tree
= proto_item_add_subtree(ti
, ett_lorawan_mac_commands
);
738 command
= tvb_get_uint8(tvb
, current_offset
);
740 tf
= proto_tree_add_item(mac_command_tree
, hf_lorawan_mac_command_uplink_type
, tvb
, current_offset
, 1, ENC_NA
);
742 proto_item_append_text(tf
, " (%s)", val_to_str_const(command
, lorawan_mac_uplink_commandnames
, "RFU"));
744 case LORAWAN_MAC_COMMAND_UP_LINK_CHECK_REQ
:
745 case LORAWAN_MAC_COMMAND_UP_DUTY_ANS
:
746 case LORAWAN_MAC_COMMAND_UP_RX_TIMING_ANS
:
747 case LORAWAN_MAC_COMMAND_UP_TX_PARAM_SETUP_ANS
:
748 case LORAWAN_MAC_COMMAND_UP_DEVICE_TIME_REQ
:
749 case LORAWAN_MAC_COMMAND_UP_BEACON_TIMING_REQ
:
752 case LORAWAN_MAC_COMMAND_UP_LINK_ADR_ANS
:
753 field_tree
= proto_item_add_subtree(tf
, ett_lorawan_mac_command
);
754 proto_tree_add_bitmask(field_tree
, tvb
, current_offset
, hf_lorawan_mac_command_down_link_check_ans_type
, ett_lorawan_mac_command_link_check_ans
, hfx_lorawan_mac_command_link_check_ans
, ENC_NA
);
757 case LORAWAN_MAC_COMMAND_UP_RX_SETUP_ANS
:
758 field_tree
= proto_item_add_subtree(tf
, ett_lorawan_mac_command
);
759 proto_tree_add_bitmask(field_tree
, tvb
, current_offset
, hf_lorawan_mac_command_up_rx_setup_ans_type
, ett_lorawan_mac_command_rx_setup_ans
, hfx_lorawan_mac_command_rx_setup_ans
, ENC_NA
);
762 case LORAWAN_MAC_COMMAND_UP_DEV_STATUS_ANS
:
763 field_tree
= proto_item_add_subtree(tf
, ett_lorawan_mac_command
);
764 proto_tree_add_item(field_tree
, hf_lorawan_mac_command_up_device_status_ans_battery_type
, tvb
, current_offset
, 1, ENC_NA
);
766 proto_tree_add_item(field_tree
, hf_lorawan_mac_command_up_device_status_ans_margin_type
, tvb
, current_offset
, 1, ENC_NA
);
769 case LORAWAN_MAC_COMMAND_UP_DI_CHANNEL_ANS
:
770 field_tree
= proto_item_add_subtree(tf
, ett_lorawan_mac_command
);
771 proto_tree_add_item(field_tree
, hf_lorawan_mac_command_up_di_channel_ans_type
, tvb
, current_offset
, 1, ENC_NA
);
774 case LORAWAN_MAC_COMMAND_UP_NEW_CHANNEL_ANS
:
775 field_tree
= proto_item_add_subtree(tf
, ett_lorawan_mac_command
);
776 proto_tree_add_bitmask(field_tree
, tvb
, current_offset
, hf_lorawan_mac_command_up_new_channel_ans_type
, ett_lorawan_mac_command_new_channel_ans
, hfx_lorawan_mac_command_new_channel_ans
, ENC_NA
);
779 case LORAWAN_MAC_COMMAND_UP_PING_SLOT_INFO_REQ
:
780 field_tree
= proto_item_add_subtree(tf
, ett_lorawan_mac_command
);
781 proto_tree_add_item(field_tree
, hf_lorawan_mac_command_up_ping_slot_info_req_type
, tvb
, current_offset
, 1, ENC_NA
);
784 case LORAWAN_MAC_COMMAND_UP_PING_SLOT_CHANNEL_ANS
:
785 field_tree
= proto_item_add_subtree(tf
, ett_lorawan_mac_command
);
786 proto_tree_add_item(field_tree
, hf_lorawan_mac_command_up_ping_slot_channel_ans_type
, tvb
, current_offset
, 1, ENC_NA
);
789 case LORAWAN_MAC_COMMAND_UP_BEACON_FREQ_ANS
:
790 field_tree
= proto_item_add_subtree(tf
, ett_lorawan_mac_command
);
791 proto_tree_add_item(field_tree
, hf_lorawan_mac_command_up_beacon_freq_ans_type
, tvb
, current_offset
, 1, ENC_NA
);
795 /* End on unknown mac command because command lengths are not explicitly given */
796 return tvb_captured_length(tvb
);
800 tf
= proto_tree_add_item(mac_command_tree
, hf_lorawan_mac_command_downlink_type
, tvb
, current_offset
, 1, ENC_NA
);
802 proto_item_append_text(tf
, " (%s)", val_to_str_const(command
, lorawan_mac_downlink_commandnames
, "RFU"));
804 case LORAWAN_MAC_COMMAND_DOWN_LINK_CHECK_ANS
:
805 field_tree
= proto_item_add_subtree(tf
, ett_lorawan_mac_command
);
806 proto_tree_add_item(field_tree
, hf_lorawan_mac_command_down_link_check_ans_margin_type
, tvb
, current_offset
, 1, ENC_NA
);
808 proto_tree_add_item(field_tree
, hf_lorawan_mac_command_down_link_check_ans_gwcnt_type
, tvb
, current_offset
, 1, ENC_NA
);
811 case LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ
:
812 field_tree
= proto_item_add_subtree(tf
, ett_lorawan_mac_command
);
813 /* Region specific */
814 proto_tree_add_item(field_tree
, hf_lorawan_mac_command_down_link_adr_req_datarate_type
, tvb
, current_offset
, 1, ENC_NA
);
815 proto_tree_add_item(field_tree
, hf_lorawan_mac_command_down_link_adr_req_txpower_type
, tvb
, current_offset
, 1, ENC_NA
);
817 proto_tree_add_bitmask(field_tree
, tvb
, current_offset
, hf_lorawan_mac_command_down_link_adr_req_channel_type
, ett_lorawan_mac_command_link_adr_req_channel
, hfx_lorawan_mac_command_link_adr_req_channel
, ENC_LITTLE_ENDIAN
);
819 proto_tree_add_item(field_tree
, hf_lorawan_mac_command_down_link_adr_req_channel_mask_control_type
, tvb
, current_offset
, 1, ENC_NA
);
820 proto_tree_add_item(field_tree
, hf_lorawan_mac_command_down_link_adr_req_repetitions_type
, tvb
, current_offset
, 1, ENC_NA
);
823 case LORAWAN_MAC_COMMAND_DOWN_DUTY_REQ
:
824 field_tree
= proto_item_add_subtree(tf
, ett_lorawan_mac_command
);
825 proto_tree_add_item(field_tree
, hf_lorawan_mac_command_down_dutycycle_type
, tvb
, current_offset
, 1, ENC_NA
);
828 case LORAWAN_MAC_COMMAND_DOWN_RX_SETUP_REQ
:
829 field_tree
= proto_item_add_subtree(tf
, ett_lorawan_mac_command
);
830 proto_tree_add_item(field_tree
, hf_lorawan_mac_command_down_rx_setup_req_rx1droffset_type
, tvb
, current_offset
, 1, ENC_NA
);
831 /* Region specific */
832 proto_tree_add_item(field_tree
, hf_lorawan_mac_command_down_rx_setup_req_rx2datarate_type
, tvb
, current_offset
, 1, ENC_NA
);
834 proto_tree_add_item(field_tree
, hf_lorawan_mac_command_down_rx_setup_req_frequency_type
, tvb
, current_offset
, 3, ENC_LITTLE_ENDIAN
);
837 case LORAWAN_MAC_COMMAND_DOWN_DEV_STATUS_REQ
:
838 case LORAWAN_MAC_COMMAND_DOWN_PING_SLOT_INFO_ANS
:
841 case LORAWAN_MAC_COMMAND_DOWN_NEW_CHANNEL_REQ
:
842 field_tree
= proto_item_add_subtree(tf
, ett_lorawan_mac_command
);
843 proto_tree_add_item(field_tree
, hf_lorawan_mac_command_down_new_channel_req_index_type
, tvb
, current_offset
, 1, ENC_NA
);
845 proto_tree_add_item(field_tree
, hf_lorawan_mac_command_down_new_channel_req_frequency_type
, tvb
, current_offset
, 3, ENC_LITTLE_ENDIAN
);
847 /* Region specific */
848 proto_tree_add_item(field_tree
, hf_lorawan_mac_command_down_new_channel_req_drrange_max_type
, tvb
, current_offset
, 1, ENC_NA
);
849 /* Region specific */
850 proto_tree_add_item(field_tree
, hf_lorawan_mac_command_down_new_channel_req_drrange_min_type
, tvb
, current_offset
, 1, ENC_NA
);
853 case LORAWAN_MAC_COMMAND_DOWN_RX_TIMING_REQ
:
854 field_tree
= proto_item_add_subtree(tf
, ett_lorawan_mac_command
);
855 proto_tree_add_item(field_tree
, hf_lorawan_mac_command_down_rx_timing_req_delay_type
, tvb
, current_offset
, 1, ENC_NA
);
858 case LORAWAN_MAC_COMMAND_DOWN_TX_PARAM_SETUP_REQ
:
859 field_tree
= proto_item_add_subtree(tf
, ett_lorawan_mac_command
);
860 proto_tree_add_item(field_tree
, hf_lorawan_mac_command_down_tx_param_setup_req_type
, tvb
, current_offset
, 1, ENC_NA
);
863 case LORAWAN_MAC_COMMAND_DOWN_DI_CHANNEL_REQ
:
864 field_tree
= proto_item_add_subtree(tf
, ett_lorawan_mac_command
);
865 proto_tree_add_item(field_tree
, hf_lorawan_mac_command_down_di_channel_req_type
, tvb
, current_offset
, 4, ENC_NA
);
868 case LORAWAN_MAC_COMMAND_DOWN_DEVICE_TIME_ANS
:
869 case LORAWAN_MAC_COMMAND_DOWN_BEACON_TIMING_ANS
:
870 /* The time provided is the GPS time at the end of the uplink transmission. The
871 * command has a 5-octet payload defined as follows:
872 * 32-bit unsigned integer: seconds since epoch
873 * 8-bit unsigned integer: fractional-second in 1/256s increments
875 field_tree
= proto_item_add_subtree(tf
, ett_lorawan_mac_command
);
876 proto_tree_add_item(field_tree
, hf_lorawan_mac_command_down_device_time_ans_type
, tvb
, current_offset
, 5, ENC_NA
);
879 case LORAWAN_MAC_COMMAND_DOWN_PING_SLOT_CHANNEL_REQ
:
880 field_tree
= proto_item_add_subtree(tf
, ett_lorawan_mac_command
);
881 proto_tree_add_item(field_tree
, hf_lorawan_mac_command_down_ping_slot_channel_req_type
, tvb
, current_offset
, 4, ENC_NA
);
884 case LORAWAN_MAC_COMMAND_DOWN_BEACON_FREQ_REQ
:
885 field_tree
= proto_item_add_subtree(tf
, ett_lorawan_mac_command
);
886 proto_tree_add_item(field_tree
, hf_lorawan_mac_command_down_beacon_freq_req_type
, tvb
, current_offset
, 3, ENC_NA
);
890 /* End on unknown mac command because command lengths are not explicitly given */
891 return tvb_captured_length(tvb
);
895 } while (tvb_captured_length_remaining(tvb
, current_offset
));
896 return tvb_captured_length(tvb
);
900 dissect_lorawan_beacon(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree _U_
)
903 proto_tree
*gwspecific_tree
;
904 int32_t current_offset
= 0;
905 unsigned length
= tvb_reported_length(tvb
);
906 uint16_t calc_crc1
, calc_crc2
;
909 proto_tree_add_string(tree
, hf_lorawan_msgtype_type
, tvb
, current_offset
, 0, val_to_str_const(LORAWAN_MAC_BEACON
, lorawan_ftypenames
, "RFU"));
912 calc_crc1
= crc16_r3_ccitt_tvb(tvb
, 0, 6);
913 calc_crc2
= crc16_r3_ccitt_tvb(tvb
, 8, 7);
914 proto_tree_add_item(tree
, hf_lorawan_beacon_rfu1_type
, tvb
, current_offset
, 2, ENC_NA
);
917 calc_crc1
= crc16_r3_ccitt_tvb(tvb
, 0, 7);
918 calc_crc2
= crc16_r3_ccitt_tvb(tvb
, 9, 8);
919 proto_tree_add_item(tree
, hf_lorawan_beacon_rfu1_type
, tvb
, current_offset
, 3, ENC_NA
);
922 utctime
= gps_to_utctime(tvb_get_uint32(tvb
, current_offset
, ENC_LITTLE_ENDIAN
));
923 proto_tree_add_time(tree
, hf_lorawan_beacon_time_type
, tvb
, current_offset
, 4, &utctime
);
925 proto_tree_add_checksum(tree
, tvb
, current_offset
, hf_lorawan_beacon_crc1_type
, hf_lorawan_beacon_crc1_status_type
, NULL
, pinfo
, calc_crc1
, ENC_LITTLE_ENDIAN
, PROTO_CHECKSUM_VERIFY
);
928 ti
= proto_tree_add_item(tree
, hf_lorawan_beacon_gwspecific_type
, tvb
, current_offset
, 7, ENC_NA
);
929 gwspecific_tree
= proto_item_add_subtree(ti
, ett_lorawan_beacon_gwspecific
);
930 proto_tree_add_item(gwspecific_tree
, hf_lorawan_beacon_gwspecific_infodesc_type
, tvb
, current_offset
, 1, ENC_NA
);
932 proto_tree_add_item(gwspecific_tree
, hf_lorawan_beacon_gwspecific_lat_type
, tvb
, current_offset
, 3, ENC_LITTLE_ENDIAN
);
934 proto_tree_add_item(gwspecific_tree
, hf_lorawan_beacon_gwspecific_lng_type
, tvb
, current_offset
, 3, ENC_LITTLE_ENDIAN
);
938 proto_tree_add_item(tree
, hf_lorawan_beacon_rfu2_type
, tvb
, current_offset
, 1, ENC_NA
);
941 proto_tree_add_checksum(tree
, tvb
, current_offset
, hf_lorawan_beacon_crc2_type
, hf_lorawan_beacon_crc2_status_type
, NULL
, pinfo
, calc_crc2
, ENC_LITTLE_ENDIAN
, PROTO_CHECKSUM_VERIFY
);
943 return tvb_captured_length(tvb
);
947 dissect_lorawan_join_request(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree _U_
)
950 proto_tree
*field_tree
;
951 int32_t current_offset
= 1;
953 tf
= proto_tree_add_item(tree
, hf_lorawan_join_request_type
, tvb
, current_offset
, 18, ENC_NA
);
954 field_tree
= proto_item_add_subtree(tf
, ett_lorawan_join_request
);
955 proto_tree_add_item(field_tree
, hf_lorawan_join_request_joineui_type
, tvb
, current_offset
, 8, ENC_LITTLE_ENDIAN
);
957 proto_tree_add_item(field_tree
, hf_lorawan_join_request_deveui_type
, tvb
, current_offset
, 8, ENC_LITTLE_ENDIAN
);
959 proto_tree_add_item(field_tree
, hf_lorawan_join_request_devnonce_type
, tvb
, current_offset
, 2, ENC_LITTLE_ENDIAN
);
963 * cmac = aes128_cmac(AppKey, msg)
966 root_key_t
*root_key
= get_root_key(tvb_get_ptr(tvb
, current_offset
- 10, 8));
968 proto_tree_add_checksum(tree
, tvb
, current_offset
, hf_lorawan_mic_type
, hf_lorawan_mic_status_type
, &ei_lorawan_mic
, pinfo
,
969 calculate_mic(tvb_get_ptr(tvb
, 0, current_offset
), current_offset
, root_key
->appkey
->data
), ENC_LITTLE_ENDIAN
, PROTO_CHECKSUM_VERIFY
);
971 proto_item
*checksum_item
= proto_tree_add_checksum(tree
, tvb
, current_offset
, hf_lorawan_mic_type
, hf_lorawan_mic_status_type
, NULL
, pinfo
,
972 0, ENC_LITTLE_ENDIAN
, PROTO_CHECKSUM_NO_FLAGS
);
973 expert_add_info(pinfo
, checksum_item
, &ei_lorawan_missing_keys
);
976 return tvb_captured_length(tvb
);
980 dissect_lorawan_join_accept(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree _U_
)
983 proto_tree
*field_tree
;
984 int32_t current_offset
= 1;
985 root_key_t
*root_key
= NULL
;
987 int length
= tvb_captured_length_remaining(tvb
, current_offset
);
988 tf
= proto_tree_add_item(tree
, hf_lorawan_join_accept_type
, tvb
, current_offset
, 12, ENC_NA
);
989 field_tree
= proto_item_add_subtree(tf
, ett_lorawan_join_accept
);
991 /* Join-Accept may be either 16B or 32B long (including MIC) */
992 if (length
!= 16 && length
!= 32) {
993 expert_add_info(pinfo
, field_tree
, &ei_lorawan_length_error
);
994 proto_tree_add_item(tree
, hf_lorawan_frame_payload_type
, tvb
, current_offset
, tvb_captured_length_remaining(tvb
, current_offset
), ENC_NA
);
995 return tvb_captured_length(tvb
);
998 /* Iterate through all available root keys for Join-Accept */
999 uint8_t *decrypted_buffer
= (uint8_t *)wmem_alloc0(pinfo
->pool
, length
);
1000 uint8_t *mic_buffer
= (uint8_t *)wmem_alloc0(pinfo
->pool
, length
- 4 + 1);
1002 for (unsigned key_idx
= 0; key_idx
< root_num_keys
; key_idx
++) {
1003 if (aes128_lorawan_encrypt(root_keys
[key_idx
].appkey
->data
, tvb_get_ptr(tvb
, current_offset
, length
), decrypted_buffer
, length
)) {
1004 mic_buffer
[0] = tvb_get_uint8(tvb
, current_offset
- 1); // unencrypted MHDR
1005 memcpy(&mic_buffer
[1], decrypted_buffer
, length
- 4); // decrypted Join-Accept
1006 memcpy(&mic_check
, &decrypted_buffer
[length
- 4], 4); // decrypted MIC
1008 // check for valid MIC of payload decrypted using current AppKey
1009 if (calculate_mic(mic_buffer
, length
- 4 + 1, root_keys
[key_idx
].appkey
->data
) == mic_check
) {
1010 root_key
= &root_keys
[key_idx
];
1017 tvbuff_t
*next_tvb
= tvb_new_child_real_data(tvb
, decrypted_buffer
, length
, length
);
1018 add_new_data_source(pinfo
, next_tvb
, "Decrypted payload");
1021 proto_tree_add_item(field_tree
, hf_lorawan_join_accept_joinnonce_type
, next_tvb
, current_offset
, 3, ENC_LITTLE_ENDIAN
);
1022 current_offset
+= 3;
1023 proto_tree_add_item(field_tree
, hf_lorawan_join_accept_netid_type
, next_tvb
, current_offset
, 3, ENC_LITTLE_ENDIAN
);
1024 current_offset
+= 3;
1025 proto_tree_add_item(field_tree
, hf_lorawan_join_accept_devaddr_type
, next_tvb
, current_offset
, 4, ENC_LITTLE_ENDIAN
);
1026 current_offset
+= 4;
1027 proto_tree_add_bitmask(field_tree
, next_tvb
, current_offset
, hf_lorawan_join_accept_dlsettings_type
, ett_lorawan_join_accept_dlsettings
, hfx_lorawan_join_accept_dlsettings
, ENC_NA
);
1029 proto_tree_add_item(field_tree
, hf_lorawan_join_accept_rxdelay_type
, next_tvb
, current_offset
, 1, ENC_NA
);
1031 if (tvb_captured_length(next_tvb
) - current_offset
> 4) {
1032 proto_tree_add_item(field_tree
, hf_lorawan_join_accept_cflist_type
, next_tvb
, current_offset
, 16, ENC_NA
);
1033 current_offset
+= 16;
1034 proto_item_set_len(tf
, proto_item_get_len(tf
) + 16);
1037 proto_tree_add_checksum(tree
, next_tvb
, current_offset
, hf_lorawan_mic_type
, hf_lorawan_mic_status_type
, &ei_lorawan_mic
, pinfo
, 0, ENC_LITTLE_ENDIAN
, PROTO_CHECKSUM_VERIFY
| PROTO_CHECKSUM_ZERO
);
1039 expert_add_info(pinfo
, field_tree
, &ei_lorawan_missing_keys
);
1040 proto_tree_add_item(tree
, hf_lorawan_frame_payload_type
, tvb
, current_offset
, tvb_captured_length_remaining(tvb
, current_offset
), ENC_NA
);
1043 return tvb_captured_length(tvb
);
1047 dissect_lorawan_data(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree _U_
, bool uplink
)
1049 proto_item
*ti
= NULL
, *tf
;
1050 proto_tree
*field_tree
;
1051 int32_t current_offset
= 1;
1052 uint8_t fopts_length
= (tvb_get_uint8(tvb
, current_offset
+ 4) & LORAWAN_FRAME_FOPTSLEN_MASK
);
1056 tf
= proto_tree_add_item(tree
, hf_lorawan_frame_header_type
, tvb
, current_offset
, 7 + fopts_length
, ENC_NA
);
1057 field_tree
= proto_item_add_subtree(tf
, ett_lorawan_frame_header
);
1058 proto_tree_add_item(field_tree
, hf_lorawan_frame_header_address_type
, tvb
, current_offset
, 4, ENC_LITTLE_ENDIAN
);
1059 uint32_t dev_address
= tvb_get_uint32(tvb
, current_offset
, ENC_LITTLE_ENDIAN
);
1060 current_offset
+= 4;
1061 proto_tree_add_bitmask(field_tree
, tvb
, current_offset
, hf_lorawan_frame_header_frame_control_type
, ett_lorawan_frame_header_control
, hfx_lorawan_frame_header_frame_control
, ENC_NA
);
1063 proto_tree_add_item(field_tree
, hf_lorawan_frame_header_frame_counter_type
, tvb
, current_offset
, 2, ENC_LITTLE_ENDIAN
);
1064 uint32_t fcnt
= tvb_get_uint16(tvb
, current_offset
, ENC_LITTLE_ENDIAN
);
1065 current_offset
+= 2;
1068 * If fopts_length > 0 then MAC commands are present in fopts field and port cannot be 0
1069 * If fopts_length == 0 then port can be any value
1070 * If port == 0 then MAC commands are in frame payload
1073 if (fopts_length
> 0) {
1074 tvbuff_t
*next_tvb
= tvb_new_subset_length(tvb
, current_offset
, fopts_length
);
1075 current_offset
+= dissect_lorawan_mac_commands(next_tvb
, pinfo
, tree
, uplink
);
1078 if (tvb_captured_length_remaining(tvb
, current_offset
) > 4) {
1080 proto_tree_add_item(tree
, hf_lorawan_frame_fport_type
, tvb
, current_offset
, 1, ENC_NA
);
1081 fport
= tvb_get_uint8(tvb
, current_offset
);
1085 if ((fopts_length
> 0) && (fport
== 0)) {
1086 /* TODO?: error, not allowed */
1089 uint8_t frmpayload_length
= tvb_captured_length_remaining(tvb
, current_offset
) - 4;
1090 if (frmpayload_length
> 0) {
1091 ti
= proto_tree_add_item(tree
, hf_lorawan_frame_payload_type
, tvb
, current_offset
, frmpayload_length
, ENC_NA
);
1094 session_key_t
*session_key
= get_session_key(dev_address
);
1095 if (session_key
&& frmpayload_length
> 0) {
1096 uint8_t padded_length
= LORAWAN_AES_PADDEDSIZE(frmpayload_length
);
1097 uint8_t *decrypted_buffer
= (uint8_t *)wmem_alloc0(pinfo
->pool
, padded_length
);
1098 uint8_t *encrypted_buffer
= (uint8_t *)wmem_alloc0(pinfo
->pool
, padded_length
);
1099 tvb_memcpy(tvb
, encrypted_buffer
, current_offset
, frmpayload_length
);
1100 if (decrypt_lorawan_frame_payload(encrypted_buffer
, padded_length
, decrypted_buffer
, (fport
== 0) ? session_key
->nwkskey
->data
: session_key
->appskey
->data
, !uplink
, dev_address
, fcnt
)) {
1101 tvbuff_t
*next_tvb
= tvb_new_child_real_data(tvb
, decrypted_buffer
, frmpayload_length
, frmpayload_length
);
1102 add_new_data_source(pinfo
, next_tvb
, "Decrypted payload");
1103 proto_tree
*frame_payload_decrypted_tree
= proto_item_add_subtree(ti
, ett_lorawan_frame_payload_decrypted
);
1105 current_offset
+= dissect_lorawan_mac_commands(next_tvb
, pinfo
, tree
, uplink
);
1108 * fport values 0x01 - 0xDF are application specific
1109 * fport values 0xE0 - 0xFF are reserved for future extensions
1111 proto_tree_add_bytes(frame_payload_decrypted_tree
, hf_lorawan_frame_payload_decrypted_type
, next_tvb
, 0, frmpayload_length
, decrypted_buffer
);
1112 current_offset
+= frmpayload_length
;
1115 proto_tree_add_expert_format(tree
, pinfo
, &ei_lorawan_decrypting_error
, tvb
, current_offset
, 4, "Decrypting error");
1116 current_offset
+= frmpayload_length
;
1119 current_offset
+= frmpayload_length
;
1124 * cmac = aes128_cmac(NwkSKey, B0 | msg)
1126 * B0 = 0x49 | 0x00 | 0x00 | 0x00 | 0x00 | dir | devAddr | fcntup/fcntdown | len(msg)
1129 int frame_length
= current_offset
;
1130 uint8_t *msg
= (uint8_t *)wmem_alloc0(pinfo
->pool
, frame_length
+ 16);
1132 msg
[5] = uplink
? 0 : 1;
1133 memcpy(msg
+ 6, &dev_address
, 4);
1134 memcpy(msg
+ 10, &fcnt
, 4);
1135 msg
[15] = frame_length
;
1136 tvb_memcpy(tvb
, msg
+ 16, 0, frame_length
);
1137 proto_tree_add_checksum(tree
, tvb
, current_offset
, hf_lorawan_mic_type
, hf_lorawan_mic_status_type
, &ei_lorawan_mic
, pinfo
, calculate_mic(msg
, frame_length
+ 16, session_key
->nwkskey
->data
), ENC_LITTLE_ENDIAN
, PROTO_CHECKSUM_VERIFY
);
1139 proto_item
*checksum_item
= proto_tree_add_checksum(tree
, tvb
, current_offset
, hf_lorawan_mic_type
, hf_lorawan_mic_status_type
, NULL
, pinfo
,
1140 0, ENC_LITTLE_ENDIAN
, PROTO_CHECKSUM_NO_FLAGS
);
1141 expert_add_info(pinfo
, checksum_item
, &ei_lorawan_missing_keys
);
1144 return tvb_captured_length(tvb
);
1148 dissect_lorawan(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, void *data _U_
)
1150 proto_item
*ti
, *tf
;
1151 proto_tree
*lorawan_tree
, *field_tree
;
1152 int32_t current_offset
= 0;
1154 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "LoRaWAN");
1155 col_clear(pinfo
->cinfo
,COL_INFO
);
1156 ti
= proto_tree_add_item(tree
, proto_lorawan
, tvb
, 0, -1, ENC_NA
);
1157 lorawan_tree
= proto_item_add_subtree(ti
, ett_lorawan
);
1159 /* Detect and dissect Class-B beacon frames
1160 * common mark: beacon is 17B or 19B long and begins with 2 bytes of zeroed RFU
1162 uint16_t classb_rfu
= tvb_get_uint16(tvb
, current_offset
, ENC_LITTLE_ENDIAN
);
1163 unsigned classb_length
= tvb_reported_length(tvb
);
1164 if (classb_rfu
== 0x0000 && (classb_length
== 17 || classb_length
== 19)) {
1165 return dissect_lorawan_beacon(tvb
, pinfo
, lorawan_tree
);
1169 uint8_t mac_ftype
= LORAWAN_MAC_FTYPE(tvb_get_uint8(tvb
, current_offset
));
1170 proto_tree_add_string(lorawan_tree
, hf_lorawan_msgtype_type
, tvb
, current_offset
, 0, val_to_str_const(mac_ftype
, lorawan_ftypenames
, "RFU"));
1171 tf
= proto_tree_add_item(lorawan_tree
, hf_lorawan_mac_header_type
, tvb
, current_offset
, 1, ENC_NA
);
1172 proto_item_append_text(tf
, " (Message Type: %s, Major Version: %s)",
1173 val_to_str_const(mac_ftype
, lorawan_ftypenames
, "RFU"),
1174 val_to_str_const(LORAWAN_MAC_MAJOR(tvb_get_uint8(tvb
, current_offset
)), lorawan_majornames
, "RFU"));
1176 /* Validate MHDR fields for LoRaWAN packet, do not dissect malformed packets */
1177 if ((tvb_get_uint8(tvb
, current_offset
) & (LORAWAN_MAC_MAJOR_MASK
| LORAWAN_MAC_RFU_MASK
)) != LORAWAN_MAC_MAJOR_R1
) {
1178 expert_add_info(pinfo
, lorawan_tree
, &ei_lorawan_mhdr_error
);
1179 mac_ftype
= LORAWAN_MAC_FTYPE_RFU
;
1182 field_tree
= proto_item_add_subtree(tf
, ett_lorawan_mac_header
);
1183 proto_tree_add_item(field_tree
, hf_lorawan_mac_header_ftype_type
, tvb
, current_offset
, 1, ENC_NA
);
1184 proto_tree_add_item(field_tree
, hf_lorawan_mac_header_rfu_type
, tvb
, current_offset
, 1, ENC_NA
);
1185 proto_tree_add_item(field_tree
, hf_lorawan_mac_header_major_type
, tvb
, current_offset
, 1, ENC_NA
);
1188 switch (mac_ftype
) {
1189 case LORAWAN_MAC_FTYPE_JOINREQUEST
:
1190 return dissect_lorawan_join_request(tvb
, pinfo
, lorawan_tree
);
1192 case LORAWAN_MAC_FTYPE_JOINACCEPT
:
1193 return dissect_lorawan_join_accept(tvb
, pinfo
, lorawan_tree
);
1195 case LORAWAN_MAC_FTYPE_UNCONFIRMEDDATAUP
:
1196 case LORAWAN_MAC_FTYPE_CONFIRMEDDATAUP
:
1197 return dissect_lorawan_data(tvb
, pinfo
, lorawan_tree
, true /*uplink*/);
1199 case LORAWAN_MAC_FTYPE_UNCONFIRMEDDATADOWN
:
1200 case LORAWAN_MAC_FTYPE_CONFIRMEDDATADOWN
:
1201 return dissect_lorawan_data(tvb
, pinfo
, lorawan_tree
, false /*downlink*/);
1203 default: /* LORAWAN_MAC_FTYPE_RFU or LORAWAN_MAC_FTYPE_PROPRIETARY */
1204 proto_tree_add_item(lorawan_tree
, hf_lorawan_frame_payload_type
, tvb
, current_offset
, tvb_captured_length_remaining(tvb
, current_offset
), ENC_NA
);
1205 return tvb_captured_length(tvb
);
1210 proto_register_lorawan(void)
1212 static hf_register_info hf
[] = {
1213 { &hf_lorawan_msgtype_type
,
1214 { "Message type", "lorawan.msgtype",
1215 FT_STRING
, BASE_NONE
,
1219 { &hf_lorawan_mac_header_type
,
1220 { "MAC Header", "lorawan.mhdr",
1223 "[MHDR] MAC Header", HFILL
}
1225 { &hf_lorawan_mac_header_ftype_type
,
1226 { "Message Type", "lorawan.mhdr.ftype",
1228 VALS(lorawan_ftypenames
), LORAWAN_MAC_FTYPE_MASK
,
1229 "[FType] Message Type", HFILL
}
1231 { &hf_lorawan_mac_header_rfu_type
,
1232 { "RFU", "lorawan.mhdr.rfu",
1234 NULL
, LORAWAN_MAC_RFU_MASK
,
1237 { &hf_lorawan_mac_header_major_type
,
1238 { "Major Version", "lorawan.mhdr.major",
1240 VALS(lorawan_majornames
), LORAWAN_MAC_MAJOR_MASK
,
1241 "[Major] Major Version", HFILL
}
1243 { &hf_lorawan_mac_commands_type
,
1244 { "MAC Commands", "lorawan.mac_commands",
1249 { &hf_lorawan_mac_command_uplink_type
,
1250 { "Uplink Command", "lorawan.mac_command_uplink",
1252 VALS(lorawan_mac_uplink_commandnames
), 0x0,
1255 { &hf_lorawan_mac_command_downlink_type
,
1256 { "Downlink Command", "lorawan.mac_command_downlink",
1258 VALS(lorawan_mac_downlink_commandnames
), 0x0,
1261 { &hf_lorawan_mac_command_down_link_check_ans_type
,
1262 { "Link Check Answer", "lorawan.link_check_answer",
1267 { &hf_lorawan_mac_command_down_link_check_ans_margin_type
,
1268 { "Demodulation Margin", "lorawan.link_check_answer.margin",
1269 FT_UINT8
, BASE_DEC
|BASE_UNIT_STRING
,
1270 UNS(&units_decibels
), 0x0,
1273 { &hf_lorawan_mac_command_down_link_check_ans_gwcnt_type
,
1274 { "Gateway Count", "lorawan.link_check_answer.gwcnt",
1279 { &hf_lorawan_mac_command_down_link_adr_req_datarate_type
,
1280 { "Data Rate", "lorawan.link_adr_request.datarate",
1282 NULL
, LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_DATARATE_MASK
,
1285 { &hf_lorawan_mac_command_down_link_adr_req_txpower_type
,
1286 { "Transmit Power", "lorawan.link_adr_request.txpower",
1288 NULL
, LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_TXPOWER_MASK
,
1291 { &hf_lorawan_mac_command_down_link_adr_req_channel_type
,
1292 { "Channel 1", "lorawan.link_adr_request.channel",
1293 FT_UINT16
, BASE_HEX
,
1297 { &hf_lorawan_mac_command_down_link_adr_req_channel1_type
,
1298 { "Channel 1", "lorawan.link_adr_request.channel.1",
1300 NULL
, LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_1_MASK
,
1303 { &hf_lorawan_mac_command_down_link_adr_req_channel2_type
,
1304 { "Channel 2", "lorawan.link_adr_request.channel.2",
1306 NULL
, LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_2_MASK
,
1309 { &hf_lorawan_mac_command_down_link_adr_req_channel3_type
,
1310 { "Channel 3", "lorawan.link_adr_request.channel.3",
1312 NULL
, LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_3_MASK
,
1315 { &hf_lorawan_mac_command_down_link_adr_req_channel4_type
,
1316 { "Channel 4", "lorawan.link_adr_request.channel.4",
1318 NULL
, LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_4_MASK
,
1321 { &hf_lorawan_mac_command_down_link_adr_req_channel5_type
,
1322 { "Channel 5", "lorawan.link_adr_request.channel.5",
1324 NULL
, LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_5_MASK
,
1327 { &hf_lorawan_mac_command_down_link_adr_req_channel6_type
,
1328 { "Channel 6", "lorawan.link_adr_request.channel.6",
1330 NULL
, LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_6_MASK
,
1333 { &hf_lorawan_mac_command_down_link_adr_req_channel7_type
,
1334 { "Channel 7", "lorawan.link_adr_request.channel.7",
1336 NULL
, LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_7_MASK
,
1339 { &hf_lorawan_mac_command_down_link_adr_req_channel8_type
,
1340 { "Channel 8", "lorawan.link_adr_request.channel.8",
1342 NULL
, LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_8_MASK
,
1345 { &hf_lorawan_mac_command_down_link_adr_req_channel9_type
,
1346 { "Channel 9", "lorawan.link_adr_request.channel.9",
1348 NULL
, LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_9_MASK
,
1351 { &hf_lorawan_mac_command_down_link_adr_req_channel10_type
,
1352 { "Channel 10", "lorawan.link_adr_request.channel.10",
1354 NULL
, LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_10_MASK
,
1357 { &hf_lorawan_mac_command_down_link_adr_req_channel11_type
,
1358 { "Channel 11", "lorawan.link_adr_request.channel.11",
1360 NULL
, LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_11_MASK
,
1363 { &hf_lorawan_mac_command_down_link_adr_req_channel12_type
,
1364 { "Channel 12", "lorawan.link_adr_request.channel.12",
1366 NULL
, LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_12_MASK
,
1369 { &hf_lorawan_mac_command_down_link_adr_req_channel13_type
,
1370 { "Channel 13", "lorawan.link_adr_request.channel.13",
1372 NULL
, LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_13_MASK
,
1375 { &hf_lorawan_mac_command_down_link_adr_req_channel14_type
,
1376 { "Channel 14", "lorawan.link_adr_request.channel.14",
1378 NULL
, LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_14_MASK
,
1381 { &hf_lorawan_mac_command_down_link_adr_req_channel15_type
,
1382 { "Channel 15", "lorawan.link_adr_request.channel.15",
1384 NULL
, LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_15_MASK
,
1387 { &hf_lorawan_mac_command_down_link_adr_req_channel16_type
,
1388 { "Channel 16", "lorawan.link_adr_request.channel.16",
1390 NULL
, LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHANNEL_16_MASK
,
1393 { &hf_lorawan_mac_command_down_link_adr_req_channel_mask_control_type
,
1394 { "Channel Mask Control", "lorawan.link_adr_request.chmaskctl",
1396 NULL
, LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_CHMASKCNTL_MASK
,
1399 { &hf_lorawan_mac_command_down_link_adr_req_repetitions_type
,
1400 { "Number Of Repetitions", "lorawan.link_adr_request.nbrep",
1402 NULL
, LORAWAN_MAC_COMMAND_DOWN_LINK_ADR_REQ_NBREP_MASK
,
1405 { &hf_lorawan_mac_command_up_link_adr_ans_txpower_type
,
1406 { "Transmit Power Ack", "lorawan.link_adr_response.txpower",
1408 NULL
, LORAWAN_MAC_COMMAND_UP_LINK_ADR_ANS_TXPOWER_MASK
,
1411 { &hf_lorawan_mac_command_up_link_adr_ans_datarate_type
,
1412 { "Data Rate Ack", "lorawan.link_adr_response.datarate",
1414 NULL
, LORAWAN_MAC_COMMAND_UP_LINK_ADR_ANS_DATARATE_MASK
,
1417 { &hf_lorawan_mac_command_up_link_adr_ans_channel_mask_type
,
1418 { "Channel Mask Ack", "lorawan.link_adr_response.channelmask",
1420 NULL
, LORAWAN_MAC_COMMAND_UP_LINK_ADR_ANS_CHANNEL_MASK
,
1423 { &hf_lorawan_mac_command_down_dutycycle_type
,
1424 { "Duty Cycle", "lorawan.dutycycle_request.dutycycle",
1429 { &hf_lorawan_mac_command_down_rx_setup_req_rx1droffset_type
,
1430 { "RX1 Datarate Offset", "lorawan.rx_setup_request.rx1droffset",
1432 NULL
, LORAWAN_MAC_COMMAND_DOWN_RX_SETUP_RX1DROFFSET_MASK
,
1435 { &hf_lorawan_mac_command_down_rx_setup_req_rx2datarate_type
,
1436 { "RX2 Datarate", "lorawan.rx_setup_request.rx2datarate",
1438 NULL
, LORAWAN_MAC_COMMAND_DOWN_RX_SETUP_RX2DATARATE_MASK
,
1441 { &hf_lorawan_mac_command_down_rx_setup_req_frequency_type
,
1442 { "Frequency", "lorawan.rx_setup_request.frequency",
1443 FT_UINT24
, BASE_DEC
|BASE_UNIT_STRING
,
1444 UNS(&units_hz
), 0x0,
1447 { &hf_lorawan_mac_command_up_rx_setup_ans_type
,
1448 { "RX Setup Response", "lorawan.rx_setup_response",
1453 { &hf_lorawan_mac_command_up_rx_setup_ans_rx1droffset_type
,
1454 { "RX1 Datarate Offset Ack", "lorawan.rx_setup_response.rx1droffset",
1456 NULL
, LORAWAN_MAC_COMMAND_UP_RX_SETUP_ANS_TXPOWER_MASK
,
1459 { &hf_lorawan_mac_command_up_rx_setup_ans_rx2datarate_type
,
1460 { "RX2 Datarate Ack", "lorawan.rx_setup_response.rx2datarate",
1462 NULL
, LORAWAN_MAC_COMMAND_UP_RX_SETUP_ANS_DATARATE_MASK
,
1465 { &hf_lorawan_mac_command_up_rx_setup_ans_frequency_type
,
1466 { "Frequency Ack", "lorawan.rx_setup_response.frequency",
1468 NULL
, LORAWAN_MAC_COMMAND_UP_RX_SETUP_ANS_CHANNEL_MASK
,
1471 { &hf_lorawan_mac_command_up_device_status_ans_battery_type
,
1472 { "Battery Level", "lorawan.device_status_response.battery",
1477 { &hf_lorawan_mac_command_up_device_status_ans_margin_type
,
1478 { "Margin", "lorawan.device_status_response.margin",
1480 NULL
, LORAWAN_MAC_COMMAND_UP_DEVICE_STATUS_ANS_MARGIN_MASK
,
1483 { &hf_lorawan_mac_command_down_new_channel_req_index_type
,
1484 { "Index", "lorawan.new_channel_request.index",
1489 { &hf_lorawan_mac_command_down_new_channel_req_frequency_type
,
1490 { "Frequency", "lorawan.new_channel_request.frequency",
1491 FT_UINT24
, BASE_DEC
|BASE_UNIT_STRING
,
1492 UNS(&units_hz
), 0x0,
1495 { &hf_lorawan_mac_command_down_new_channel_req_drrange_max_type
,
1496 { "Maximum Data Rate", "lorawan.new_channel_request.drrange_max",
1498 NULL
, LORAWAN_MAC_COMMAND_DOWN_NEW_CHANNEL_REQ_DRRANGE_MAX_MASK
,
1501 { &hf_lorawan_mac_command_down_new_channel_req_drrange_min_type
,
1502 { "Minimum Data Rate", "lorawan.new_channel_request.drrange_min",
1504 NULL
, LORAWAN_MAC_COMMAND_DOWN_NEW_CHANNEL_REQ_DRRANGE_MIN_MASK
,
1507 { &hf_lorawan_mac_command_up_new_channel_ans_type
,
1508 { "New Channel Response", "lorawan.new_channel_response",
1513 { &hf_lorawan_mac_command_up_new_channel_ans_datarate_type
,
1514 { "Datarate Ack", "lorawan.new_channel_response.datarate",
1516 NULL
, LORAWAN_MAC_COMMAND_UP_NEW_CHANNEL_ANS_DATARATE_MASK
,
1519 { &hf_lorawan_mac_command_up_new_channel_ans_frequency_type
,
1520 { "Frequency Ack", "lorawan.new_channel_response.frequency",
1522 NULL
, LORAWAN_MAC_COMMAND_UP_NEW_CHANNEL_ANS_FREQUENCY_MASK
,
1525 { &hf_lorawan_mac_command_down_rx_timing_req_delay_type
,
1526 { "Delay", "lorawan.rx_timing_request.delay",
1527 FT_UINT8
, BASE_DEC
|BASE_UNIT_STRING
,
1528 UNS(&units_seconds
), LORAWAN_MAC_COMMAND_DOWN_RX_TIMING_REQ_DELAY_MASK
,
1531 { &hf_lorawan_mac_command_up_di_channel_ans_type
,
1532 { "Status", "lorawan.di_channel_response",
1533 FT_BYTES
, BASE_NONE
,
1537 { &hf_lorawan_mac_command_up_ping_slot_info_req_type
,
1538 { "PingSlotParam", "lorawan.ping_slot_info_request",
1539 FT_BYTES
, BASE_NONE
,
1543 { &hf_lorawan_mac_command_up_ping_slot_channel_ans_type
,
1544 { "Status", "lorawan.ping_slot_channel_response",
1545 FT_BYTES
, BASE_NONE
,
1549 { &hf_lorawan_mac_command_up_beacon_freq_ans_type
,
1550 { "Status", "lorawan.beacon_freq_response",
1551 FT_BYTES
, BASE_NONE
,
1555 { &hf_lorawan_mac_command_down_tx_param_setup_req_type
,
1556 { "DwellTime, EIRP", "lorawan.tx_param_setup_request",
1557 FT_BYTES
, BASE_NONE
,
1561 { &hf_lorawan_mac_command_down_di_channel_req_type
,
1562 { "ChIndex, Frequency", "lorawan.di_channel_request",
1563 FT_BYTES
, BASE_NONE
,
1567 { &hf_lorawan_mac_command_down_device_time_ans_type
,
1568 { "DeviceTimeAns", "lorawan.device_time_response",
1569 FT_BYTES
, BASE_NONE
,
1573 { &hf_lorawan_mac_command_down_ping_slot_channel_req_type
,
1574 { "Frequency, DR", "lorawan.ping_slot_channel_request",
1575 FT_BYTES
, BASE_NONE
,
1579 { &hf_lorawan_mac_command_down_beacon_freq_req_type
,
1580 { "Frequency", "lorawan.beacon_freq_request",
1581 FT_BYTES
, BASE_NONE
,
1585 { &hf_lorawan_join_request_type
,
1586 { "Join Request", "lorawan.join_request",
1591 { &hf_lorawan_join_request_joineui_type
,
1592 { "Join-Server identifier", "lorawan.join_request.joineui",
1593 FT_EUI64
, BASE_NONE
,
1595 "[JoinEUI] Join-Server identifier", HFILL
}
1597 { &hf_lorawan_join_request_deveui_type
,
1598 { "End-device identifier", "lorawan.join_request.deveui",
1599 FT_EUI64
, BASE_NONE
,
1601 "[DevEUI] End-device identifier", HFILL
}
1603 { &hf_lorawan_join_request_devnonce_type
,
1604 { "Device Nonce", "lorawan.join_request.devnonce",
1605 FT_UINT16
, BASE_DEC
,
1607 "[DevNonce] Device Nonce", HFILL
}
1609 { &hf_lorawan_join_accept_type
,
1610 { "Join Accept", "lorawan.join_accept",
1615 { &hf_lorawan_join_accept_joinnonce_type
,
1616 { "Join-Server nonce", "lorawan.join_accept.joinnonce",
1617 FT_UINT24
, BASE_HEX
,
1619 "[JoinNonce] Join-Server nonce", HFILL
}
1621 { &hf_lorawan_join_accept_netid_type
,
1622 { "Network identifier", "lorawan.join_accept.netid",
1623 FT_UINT24
, BASE_HEX
,
1625 "[NetID] Network identifier", HFILL
}
1627 { &hf_lorawan_join_accept_devaddr_type
,
1628 { "Device Address", "lorawan.join_accept.devaddr",
1629 FT_UINT32
, BASE_HEX
,
1631 "[DevAddr] Device Address", HFILL
}
1633 { &hf_lorawan_join_accept_dlsettings_type
,
1634 { "Downlink configuration", "lorawan.join_accept.dlsettings",
1637 "[DLSettings] Downlink configuration", HFILL
}
1639 { &hf_lorawan_join_accept_dlsettings_rx1droffset_type
,
1640 { "RX1 Data rate offset", "lorawan.join_accept.dlsettings.rx1droffset",
1642 NULL
, LORAWAN_JOIN_ACCEPT_RX1DROFFSET_MASK
,
1643 "[RX1DROffset] RX1 Data rate offset", HFILL
}
1645 { &hf_lorawan_join_accept_dlsettings_rx2dr_type
,
1646 { "RX2 Data rate", "lorawan.join_accept.dlsettings.rx2datarate",
1648 NULL
, LORAWAN_JOIN_ACCEPT_RX2DR_MASK
,
1649 "[RX2DataRate] RX2 Data rate", HFILL
}
1651 { &hf_lorawan_join_accept_rxdelay_type
,
1652 { "Delay between TX and RX", "lorawan.join_accept.rxdelay",
1653 FT_UINT8
, BASE_DEC
|BASE_UNIT_STRING
,
1654 UNS(&units_seconds
), 0x0,
1655 "[RXDelay] Delay between TX and RX", HFILL
}
1657 { &hf_lorawan_join_accept_cflist_type
,
1658 { "List of network parameters", "lorawan.join_accept.cflist",
1659 FT_BYTES
, BASE_NONE
,
1661 "[CFList] List of network parameters", HFILL
}
1663 { &hf_lorawan_frame_header_type
,
1664 { "Frame Header", "lorawan.fhdr",
1667 "[FHDR] Frame Header", HFILL
}
1669 { &hf_lorawan_frame_header_address_type
,
1670 { "Device Address", "lorawan.fhdr.devaddr",
1671 FT_UINT32
, BASE_HEX
,
1673 "[DevAddr] Device Address", HFILL
}
1675 { &hf_lorawan_frame_header_frame_control_type
,
1676 { "Frame Control", "lorawan.fhdr.fctrl",
1679 "[FCtrl] Frame Control", HFILL
}
1681 { &hf_lorawan_frame_header_frame_control_adr_type
,
1682 { "Adaptive Data Rate", "lorawan.fhdr.fctrl.adr",
1685 "[ADR] Adaptive Data Rate", HFILL
}
1687 { &hf_lorawan_frame_header_frame_control_adrackreq_type
,
1688 { "ADR Acknowledgement Request", "lorawan.fhdr.fctrl.adrackreq",
1691 "[ADRACKReq] ADR Acknowledgement Request(up) / RFU(down)", HFILL
}
1693 { &hf_lorawan_frame_header_frame_control_ack_type
,
1694 { "Acknowledgement", "lorawan.fhdr.fctrl.ack",
1697 "[ACK] Acknowledgement", HFILL
}
1699 { &hf_lorawan_frame_header_frame_control_fpending_type
,
1700 { "ClassB Enabled / Frame Pending", "lorawan.fhdr.fctrl.fpending",
1703 "[FPending/ClassB] ClassB Enabled (up) / Frame Pending (down)", HFILL
}
1705 { &hf_lorawan_frame_header_frame_control_foptslen_type
,
1706 { "Frame Options Length", "lorawan.fhdr.fctrl.foptslen",
1708 NULL
, LORAWAN_FRAME_FOPTSLEN_MASK
,
1709 "[FOptsLen] Frame Options Length", HFILL
}
1711 { &hf_lorawan_frame_header_frame_counter_type
,
1712 { "Frame Counter", "lorawan.fhdr.fcnt",
1713 FT_UINT16
, BASE_DEC
,
1715 "[FCnt] Frame Counter", HFILL
}
1717 { &hf_lorawan_frame_fport_type
,
1718 { "Port", "lorawan.fport",
1721 "[FPort] Port", HFILL
}
1723 { &hf_lorawan_frame_payload_type
,
1724 { "Frame Payload", "lorawan.frmpayload",
1725 FT_BYTES
, BASE_NONE
,
1727 "[FRMPayload] Frame Payload", HFILL
}
1729 { &hf_lorawan_frame_payload_decrypted_type
,
1730 { "Decrypted Frame Payload", "lorawan.frmpayload_decrypted",
1731 FT_BYTES
, BASE_NONE
,
1735 { &hf_lorawan_mic_type
,
1736 { "Message Integrity Code", "lorawan.mic",
1737 FT_UINT32
, BASE_HEX
,
1739 "[MIC] Message Integrity Code", HFILL
}
1741 { &hf_lorawan_mic_status_type
,
1742 { "Message Integrity Code Status", "lorawan.mic.status",
1743 FT_UINT8
, BASE_NONE
,
1744 VALS(proto_checksum_vals
), 0x0,
1747 { &hf_lorawan_beacon_rfu1_type
,
1748 { "RFU", "lorawan.beacon.rfu1",
1749 FT_BYTES
, BASE_NONE
,
1753 { &hf_lorawan_beacon_time_type
,
1754 { "Timestamp", "lorawan.beacon.time",
1755 FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_LOCAL
,
1757 "[Time] Timestamp", HFILL
}
1759 { &hf_lorawan_beacon_crc1_type
,
1760 { "CRC of Timestamp", "lorawan.beacon.crc1",
1761 FT_UINT16
, BASE_HEX
,
1763 "[CRC] CRC of Timestamp", HFILL
}
1765 { &hf_lorawan_beacon_crc1_status_type
,
1766 { "Beacon Timestamp CRC Status", "lorawan.beacon.crc1.status",
1767 FT_UINT8
, BASE_NONE
,
1768 VALS(proto_checksum_vals
), 0x0,
1771 { &hf_lorawan_beacon_gwspecific_type
,
1772 { "Gateway specific part", "lorawan.beacon.gwspecific",
1775 "[GwSpecific] Gateway specific part", HFILL
}
1777 { &hf_lorawan_beacon_gwspecific_infodesc_type
,
1778 { "Information descriptor", "lorawan.beacon.gwspecific.infodesc",
1781 "[InfoDesc] Information descriptor", HFILL
}
1783 { &hf_lorawan_beacon_gwspecific_lat_type
,
1784 { "GPS latitude", "lorawan.beacon.gwspecific.lat",
1785 FT_UINT24
, BASE_CUSTOM
,
1786 CF_FUNC(cf_coords_lat_custom
), 0x0,
1787 "[Lat] GPS latitude", HFILL
}
1789 { &hf_lorawan_beacon_gwspecific_lng_type
,
1790 { "GPS longitude", "lorawan.beacon.gwspecific.lng",
1791 FT_UINT24
, BASE_CUSTOM
,
1792 CF_FUNC(cf_coords_lng_custom
), 0x0,
1793 "[Lng] GPS longitude", HFILL
}
1795 { &hf_lorawan_beacon_rfu2_type
,
1796 { "RFU", "lorawan.beacon.rfu2",
1797 FT_BYTES
, BASE_NONE
,
1801 { &hf_lorawan_beacon_crc2_type
,
1802 { "CRC of GwSpecific", "lorawan.beacon.crc2",
1803 FT_UINT16
, BASE_HEX
,
1805 "[CRC] CRC of GwSpecific", HFILL
}
1807 { &hf_lorawan_beacon_crc2_status_type
,
1808 { "Beacon GwSpecific CRC Status", "lorawan.beacon.crc2.status",
1809 FT_UINT8
, BASE_NONE
,
1810 VALS(proto_checksum_vals
), 0x0,
1815 /* Setup protocol subtree array */
1816 static int *ett
[] = {
1818 &ett_lorawan_mac_header
,
1819 &ett_lorawan_mac_commands
,
1820 &ett_lorawan_mac_command
,
1821 &ett_lorawan_mac_command_link_check_ans
,
1822 &ett_lorawan_mac_command_link_adr_req_channel
,
1823 &ett_lorawan_mac_command_rx_setup_ans
,
1824 &ett_lorawan_mac_command_new_channel_ans
,
1825 &ett_lorawan_join_request
,
1826 &ett_lorawan_join_accept
,
1827 &ett_lorawan_join_accept_dlsettings
,
1828 &ett_lorawan_frame_header
,
1829 &ett_lorawan_frame_header_control
,
1830 &ett_lorawan_frame_payload_decrypted
,
1831 &ett_lorawan_beacon
,
1832 &ett_lorawan_beacon_gwspecific
,
1835 static ei_register_info ei
[] = {
1836 { &ei_lorawan_missing_keys
, { "lorawan.missing_keys", PI_PROTOCOL
, PI_NOTE
, "Missing encryption keys", EXPFILL
}},
1837 { &ei_lorawan_decrypting_error
, { "lorawan.decrypting_error", PI_DECRYPTION
, PI_ERROR
, "Error decrypting payload", EXPFILL
}},
1838 { &ei_lorawan_mic
, { "lorawan.mic_bad.expert", PI_CHECKSUM
, PI_WARN
, "Bad MIC", EXPFILL
}},
1839 { &ei_lorawan_length_error
, { "lorawan.length_error", PI_MALFORMED
, PI_ERROR
, "Field length is not according to LoRaWAN standard", EXPFILL
}},
1840 { &ei_lorawan_mhdr_error
, { "lorawan.mhdr_error", PI_MALFORMED
, PI_ERROR
, "LoRaWAN MAC Header malformed", EXPFILL
}},
1843 expert_module_t
* expert_lorawan
;
1845 proto_lorawan
= proto_register_protocol (
1846 "LoRaWAN Protocol", /* name */
1847 "LoRaWAN", /* short name */
1848 "lorawan" /* abbrev */
1851 lorawan_handle
= register_dissector("lorawan", dissect_lorawan
, proto_lorawan
);
1853 proto_register_field_array(proto_lorawan
, hf
, array_length(hf
));
1854 proto_register_subtree_array(ett
, array_length(ett
));
1856 expert_lorawan
= expert_register_protocol(proto_lorawan
);
1857 expert_register_field_array(expert_lorawan
, ei
, array_length(ei
));
1859 static uat_field_t root_keys_uat_fields
[] = {
1860 UAT_FLD_CSTRING(root_keys
, deveui_string
, "DevEUI", "LoRaWAN End-device Identifier"),
1861 UAT_FLD_CSTRING(root_keys
, appkey_string
, "AppKey", "LoRaWAN Application Key"),
1864 static uat_field_t session_keys_uat_fields
[] = {
1865 UAT_FLD_CSTRING(session_keys
, dev_addr_string
, "DevAddr", "LoRaWAN Device Address"),
1866 UAT_FLD_CSTRING(session_keys
, nwkskey_string
, "NwkSKey", "LoRaWAN Network Session Key"),
1867 UAT_FLD_CSTRING(session_keys
, appskey_string
, "AppSKey", "LoRaWAN Application Session Key"),
1871 uat_t
*root_keys_uat
= uat_new("LoRaWAN Root Keys",
1873 "root_keys_lorawan",
1877 UAT_AFFECTS_DISSECTION
| UAT_AFFECTS_FIELDS
,
1880 root_keys_update_cb
,
1884 root_keys_uat_fields
1886 uat_t
*session_keys_uat
= uat_new("LoRaWAN Session Keys",
1887 sizeof(session_key_t
),
1888 "session_keys_lorawan",
1892 UAT_AFFECTS_DISSECTION
| UAT_AFFECTS_FIELDS
,
1894 session_keys_copy_cb
,
1895 session_keys_update_cb
,
1896 session_keys_free_cb
,
1899 session_keys_uat_fields
1902 module_t
*lorawan_module
;
1903 lorawan_module
= prefs_register_protocol(proto_lorawan
, NULL
);
1904 prefs_register_uat_preference(lorawan_module
, "root_keys_lorawan", "LoRaWAN Root Keys",
1905 "A table to define root encryption keys for LoRaWAN devices, used for Join Request/Accept",
1907 prefs_register_uat_preference(lorawan_module
, "session_keys_lorawan", "LoRaWAN Session Keys",
1908 "A table to define session encryption keys for LoRaWAN devices, used for Data Up/Down",
1913 proto_reg_handoff_lorawan(void)
1915 dissector_add_uint("loratap.syncword", 0x34, lorawan_handle
);
1916 dissector_add_for_decode_as("udp.port", lorawan_handle
);
1920 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1925 * indent-tabs-mode: t
1928 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1929 * :indentSize=8:tabSize=8:noTabs=false: