2 * Network layer related functions and objects for RF4CE dissector
3 * Copyright (C) Atmosic 2023
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
14 #include <epan/packet.h>
17 #include <wsutil/array.h>
18 #include "packet-ieee802154.h"
19 #include "packet-rf4ce-secur.h"
21 #define RF4CE_MIN_NWK_LENGTH 5
22 #define RF4CE_MAX_NWK_LENGTH 148
25 #define RF4CE_NWK_PROFILE_ID_GDP 0x00
26 #define RF4CE_NWK_PROFILE_ID_ZRC10 0x01
27 #define RF4CE_NWK_PROFILE_ID_ZID 0x02
28 #define RF4CE_NWK_PROFILE_ID_ZRC20 0x03
30 #define RF4CE_PROTOABBREV_NWK "rf4ce_nwk"
31 #define RF4CE_PROTOABBREV_PROFILE "rf4ce_profile"
33 static int proto_rf4ce_nwk
;
34 static dissector_handle_t rf4ce_gdp_handle
;
37 static uat_t
*rf4ce_security_table_uat
;
39 #define RF4CE_SEC_STR_TYPE_NWK_KEY 0
40 #define RF4CE_SEC_STR_TYPE_VENDOR_SECRET 1
42 static const value_string sec_str_type_vals
[] = {
43 { RF4CE_SEC_STR_TYPE_NWK_KEY
, "NWK Key"},
44 { RF4CE_SEC_STR_TYPE_VENDOR_SECRET
, "Vendor Secret"},
48 UAT_CSTRING_CB_DEF(uat_security_records
, sec_str
, uat_security_record_t
)
49 UAT_VS_DEF(uat_security_records
, type
, uat_security_record_t
, uint8_t, 0, "NWK Key")
50 UAT_CSTRING_CB_DEF(uat_security_records
, label
, uat_security_record_t
)
52 static uat_security_record_t
*uat_security_records
;
53 static unsigned num_uat_security_records
;
55 static int ett_rf4ce_nwk
;
56 static int ett_rf4ce_nwk_payload
;
57 static int ett_rf4ce_nwk_vendor_info
;
58 static int ett_rf4ce_nwk_usr_str
;
59 static int ett_rf4ce_nwk_usr_str_class_descriptor
;
60 static int ett_rf4ce_nwk_dev_types_list
;
61 static int ett_rf4ce_nwk_profiles_list
;
63 /* RF4CE NWK header */
64 static int hf_rf4ce_nwk_fcf
;
65 static int hf_rf4ce_nwk_fcf_frame_type
;
66 static int hf_rf4ce_nwk_fcf_security_enabled
;
67 static int hf_rf4ce_nwk_fcf_protocol_version
;
68 static int hf_rf4ce_nwk_fcf_reserved
;
69 static int hf_rf4ce_nwk_fcf_channel_designator
;
70 static int hf_rf4ce_nwk_seq_num
;
71 static int hf_rf4ce_nwk_profile_id
;
72 static int hf_rf4ce_nwk_vendor_id
;
74 /* RF4CE NWK payload common */
75 static int hf_rf4ce_nwk_cmd_id
;
77 static int hf_rf4ce_nwk_node_capabilities
;
78 static int hf_rf4ce_nwk_node_capabilities_node_type
;
79 static int hf_rf4ce_nwk_node_capabilities_power_source
;
80 static int hf_rf4ce_nwk_node_capabilities_security
;
81 static int hf_rf4ce_nwk_node_capabilities_channel_normalization
;
82 static int hf_rf4ce_nwk_node_capabilities_reserved
;
84 static int hf_rf4ce_nwk_disc_req_vendor_id
;
86 #define RF4CE_NWK_VENDOR_STRING_MAX_LENGTH 7
87 static int hf_rf4ce_nwk_vendor_string
;
89 static int hf_rf4ce_nwk_app_capabilities
;
90 static int hf_rf4ce_nwk_app_capabilities_usr_str
;
91 static int hf_rf4ce_nwk_app_capabilities_supported_dev_num
;
92 static int hf_rf4ce_nwk_app_capabilities_reserved1
;
93 static int hf_rf4ce_nwk_app_capabilities_supported_profiles_num
;
94 static int hf_rf4ce_nwk_app_capabilities_reserved2
;
96 static int hf_rf4ce_nwk_usr_str
;
97 static int hf_rf4ce_nwk_usr_str_disc_rsp_app_usr_str
;
98 static int hf_rf4ce_nwk_usr_str_disc_rsp_null
;
99 static int hf_rf4ce_nwk_usr_str_disc_rsp_reserved
;
101 static int hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_tertiary
;
102 static int hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_secondary
;
103 static int hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_primary
;
105 static int hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_class_num
;
106 static int hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_duplicate_class_num_handling
;
107 static int hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_reserved
;
109 static int hf_rf4ce_nwk_usr_str_disc_rsp_discovery_lqi_threshold
;
111 #define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_MASK 0b00001111
112 #define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_DUPLICATE_CLASS_NUM_HANDLING_MASK 0b00110000
113 #define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_RESERVED_MASK 0b11000000
115 #define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_PRE_COMMISSIONED 0x00
116 #define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_BUTTON_PRESS_INDICATION 0x01
117 #define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_RESERVED_2 0x02
118 #define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_RESERVED_3 0x03
119 #define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_04 0x04
120 #define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_05 0x05
121 #define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_06 0x06
122 #define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_07 0x07
123 #define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_08 0x08
124 #define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_09 0x09
125 #define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_0A 0x0A
126 #define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_0B 0x0B
127 #define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_0C 0x0C
128 #define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_0D 0x0D
129 #define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_0E 0x0E
130 #define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_DISCOVERABLE_ONLY 0x0F
132 static const value_string rf4ce_nwk_usr_str_disc_rsp_class_desc_class_num_vals
[] = {
133 { RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_PRE_COMMISSIONED
, "Pre-Commissioned" },
134 { RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_BUTTON_PRESS_INDICATION
, "Button Press Indication" },
135 { RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_RESERVED_2
, "Reserved" },
136 { RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_RESERVED_3
, "Reserved" },
137 { RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_04
, "Implementation Specific" },
138 { RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_05
, "Implementation Specific" },
139 { RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_06
, "Implementation Specific" },
140 { RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_07
, "Implementation Specific" },
141 { RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_08
, "Implementation Specific" },
142 { RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_09
, "Implementation Specific" },
143 { RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_0A
, "Implementation Specific" },
144 { RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_0B
, "Implementation Specific" },
145 { RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_0C
, "Implementation Specific" },
146 { RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_0D
, "Implementation Specific" },
147 { RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_0E
, "Implementation Specific" },
148 { RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_DISCOVERABLE_ONLY
, "Discoverable Only" },
152 #define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_DUPLICATE_CLASS_NUM_HANDLING_AS_IS 0x00
153 #define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_DUPLICATE_CLASS_NUM_HANDLING_RECLASSIFY 0x01
154 #define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_DUPLICATE_CLASS_NUM_HANDLING_ABORT_BINDING 0x02
155 #define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_DUPLICATE_CLASS_NUM_HANDLING_RESERVED 0x03
157 static const value_string rf4ce_nwk_usr_str_disc_rsp_class_desc_duplicate_class_num_handling_vals
[] = {
158 { RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_DUPLICATE_CLASS_NUM_HANDLING_AS_IS
, "Use node descriptor as is" },
159 { RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_DUPLICATE_CLASS_NUM_HANDLING_RECLASSIFY
, "Reclassify node descriptor" },
160 { RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_DUPLICATE_CLASS_NUM_HANDLING_ABORT_BINDING
, "Abort binding" },
161 { RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_DUPLICATE_CLASS_NUM_HANDLING_RESERVED
, "Reserved" },
165 #define RF4CE_NWK_USR_STR_DISC_RSP_APP_USR_STR_LENGTH 9
167 #define RF4CE_NWK_USR_STR_PARSING_MASK_NONE 0b00000001
168 #define RF4CE_NWK_USR_STR_PARSING_MASK_DISC_RESP 0b00000010
170 static int hf_rf4ce_nwk_app_cap_dev_type
;
171 static int hf_rf4ce_nwk_app_cap_profile_id
;
173 /* RF4CE NWK Discovery Request */
174 static int hf_rf4ce_nwk_requested_dev_type
;
176 /* RF4CE NWK Discovery Response */
177 static int hf_rf4ce_nwk_disc_resp_status
;
178 static int hf_rf4ce_nwk_disc_resp_lqi
;
180 /* RF4CE NWK Pair Request */
181 static int hf_rf4ce_nwk_pair_req_nwk_addr
;
182 static int hf_rf4ce_nwk_pair_req_key_exch_num
;
184 /* RF4CE NWK Pair Response */
185 static int hf_rf4ce_nwk_pair_rsp_status
;
186 static int hf_rf4ce_nwk_pair_rsp_allocated_nwk_addr
;
187 static int hf_rf4ce_nwk_pair_rsp_nwk_addr
;
189 /* RF4CE NWK Key Seed */
190 static int hf_rf4ce_nwk_seed_seq_num
;
192 #define RF4CE_NWK_KEY_SEED_DATA_LENGTH 80
193 static int hf_rf4ce_nwk_seed_data
;
195 /* RF4CE NWK Ping Request and Response */
196 static int hf_rf4ce_nwk_ping_options
;
197 static int hf_rf4ce_nwk_ping_payload
;
200 /* Should be at the end of a decrypted NWK packet */
201 static int hf_rf4ce_nwk_mic
;
204 static int hf_rf4ce_nwk_unparsed_payload
;
206 /* Frame Control Field */
207 #define RF4CE_NWK_FCF_FRAME_TYPE_MASK 0b00000011
208 #define RF4CE_NWK_FCF_SECURITY_MASK 0b00000100
209 #define RF4CE_NWK_FCF_PROTOCOL_VERSION_MASK 0b00011000
210 #define RF4CE_NWK_FCF_RESERVED_MASK 0b00100000
211 #define RF4CE_NWK_FCF_CHANNEL_DESIGNATOR_MASK 0b11000000
214 #define RF4CE_NWK_FCF_FRAME_TYPE_RESERVED 0
215 #define RF4CE_NWK_FCF_FRAME_TYPE_DATA 1
216 #define RF4CE_NWK_FCF_FRAME_TYPE_CMD 2
217 #define RF4CE_NWK_FCF_FRAME_TYPE_VENDOR_SPECIFIC 3
219 static const value_string rf4ce_nwk_frame_types
[] = {
220 { RF4CE_NWK_FCF_FRAME_TYPE_RESERVED
, "Reserved" },
221 { RF4CE_NWK_FCF_FRAME_TYPE_DATA
, "Standard Data Frame" },
222 { RF4CE_NWK_FCF_FRAME_TYPE_CMD
, "NWK Command Frame" },
223 { RF4CE_NWK_FCF_FRAME_TYPE_VENDOR_SPECIFIC
, "Vendor-specific data frame" },
227 /* Channel Designators */
228 #define RF4CE_NWK_FCF_CHANNEL_NOT_SPECIFIED 0
229 #define RF4CE_NWK_FCF_CHANNEL_15 1
230 #define RF4CE_NWK_FCF_CHANNEL_20 2
231 #define RF4CE_NWK_FCF_CHANNEL_25 3
233 static const value_string rf4ce_nwk_channel_designators
[] = {
234 { RF4CE_NWK_FCF_CHANNEL_NOT_SPECIFIED
, "Channel not specified" },
235 { RF4CE_NWK_FCF_CHANNEL_15
, "Channel 15" },
236 { RF4CE_NWK_FCF_CHANNEL_20
, "Channel 20" },
237 { RF4CE_NWK_FCF_CHANNEL_25
, "Channel 25" },
242 #define RF4CE_NWK_PROFILE_ID_GDP 0x00
243 #define RF4CE_NWK_PROFILE_ID_ZRC10 0x01
244 #define RF4CE_NWK_PROFILE_ID_ZID 0x02
245 #define RF4CE_NWK_PROFILE_ID_ZRC20 0x03
246 #define RF4CE_NWK_PROFILE_ID_WILDCARD 0xff
249 #define RF4CE_VENDOR_ID_PANASONIC 0x0001
250 #define RF4CE_VENDOR_ID_SONY 0x0002
251 #define RF4CE_VENDOR_ID_SAMSUNG 0x0003
252 #define RF4CE_VENDOR_ID_PHILIPS 0x0004
253 #define RF4CE_VENDOR_ID_FREESCALE 0x0005
254 #define RF4CE_VENDOR_ID_OKI 0x0006
255 #define RF4CE_VENDOR_ID_TEXAS_INSTRUMENTS 0x0007
256 #define RF4CE_VENDOR_ID_TEST_1 0xfff1
257 #define RF4CE_VENDOR_ID_TEST_2 0xfff2
258 #define RF4CE_VENDOR_ID_TEST_3 0xfff3
260 static const value_string rf4ce_nwk_profile_ids
[] = {
261 { RF4CE_NWK_PROFILE_ID_GDP
, "GDP" },
262 { RF4CE_NWK_PROFILE_ID_ZRC10
, "ZRC 1.0" },
263 { RF4CE_NWK_PROFILE_ID_ZID
, "ZID" },
264 { RF4CE_NWK_PROFILE_ID_ZRC20
, "ZRC 2.0" },
269 #define RF4CE_NWK_CMD_DISCOVERY_REQ 0x01
270 #define RF4CE_NWK_CMD_DISCOVERY_RSP 0x02
271 #define RF4CE_NWK_CMD_PAIR_REQ 0x03
272 #define RF4CE_NWK_CMD_PAIR_RSP 0x04
273 #define RF4CE_NWK_CMD_UNPAIR_REQ 0x05
274 #define RF4CE_NWK_CMD_KEY_SEED 0x06
275 #define RF4CE_NWK_CMD_PING_REQ 0x07
276 #define RF4CE_NWK_CMD_PING_RSP 0x08
278 static const value_string rf4ce_nwk_cmd_names
[] = {
279 { RF4CE_NWK_CMD_DISCOVERY_REQ
, "Discovery Request" },
280 { RF4CE_NWK_CMD_DISCOVERY_RSP
, "Discovery Response" },
281 { RF4CE_NWK_CMD_PAIR_REQ
, "Pair Request" },
282 { RF4CE_NWK_CMD_PAIR_RSP
, "Pair Response" },
283 { RF4CE_NWK_CMD_UNPAIR_REQ
, "Unpair Request" },
284 { RF4CE_NWK_CMD_KEY_SEED
, "Key Seed" },
285 { RF4CE_NWK_CMD_PING_REQ
, "Ping Request" },
286 { RF4CE_NWK_CMD_PING_RSP
, "Ping Response" },
290 /* NWK Commands - Discovery Request - Node Capabilities */
291 #define RF4CE_NWK_NODE_TYPE_MASK 0b00000001
292 #define RF4CE_NWK_POWER_SOURCE_MASK 0b00000010
293 #define RF4CE_NWK_SECURITY_MASK 0b00000100
294 #define RF4CE_NWK_CHANNEL_NORMALIZATION_MASK 0b00001000
295 #define RF4CE_NWK_RESERVED_MASK 0b11110000
297 #define RF4CE_NWK_NODE_TYPE_CONTROLLER 0
298 #define RF4CE_NWK_NODE_TYPE_TARGET 1
300 static const value_string rf4ce_nwk_node_types
[] = {
301 { RF4CE_NWK_NODE_TYPE_CONTROLLER
, "Controller" },
302 { RF4CE_NWK_NODE_TYPE_TARGET
, "Target" },
306 #define RF4CE_NWK_POWER_SOURCE_NO_ALTERNATING_CURRENT_MAINS 0
307 #define RF4CE_NWK_POWER_SOURCE_ALTERNATING_CURRENT_MAINS 1
309 static const value_string rf4ce_nwk_power_sources
[] = {
310 { RF4CE_NWK_POWER_SOURCE_NO_ALTERNATING_CURRENT_MAINS
, "No Alternating Current Mains" },
311 { RF4CE_NWK_POWER_SOURCE_ALTERNATING_CURRENT_MAINS
, "Alternating Current Mains" },
315 #define RF4CE_DISC_REQ_VENDOR_ID_TEXAS_INSTRUMENTS 0x0007
316 static const value_string rf4ce_disc_req_vendor_ids
[] = {
317 { RF4CE_DISC_REQ_VENDOR_ID_TEXAS_INSTRUMENTS
, "Texas Instruments" },
321 /* NWK Commands - Discovery Request - App Capabilities */
322 #define RF4CE_NWK_USR_STR_SPECIFIED_MASK 0b00000001
323 #define RF4CE_NWK_SUPPORTED_DEV_NUM_MASK 0b00000110
324 #define RF4CE_NWK_RESERVED1_MASK 0b00001000
325 #define RF4CE_NWK_SUPPORTED_PROFILES_NUM_MASK 0b01110000
326 #define RF4CE_NWK_RESERVED2_MASK 0b10000000
328 #define RF4CE_NWK_USR_STR_LENGTH 15
329 #define RF4CE_NWK_SUPPORTED_DEV_NUM_OFFSET 1
330 #define RF4CE_NWK_SUPPORTED_PROFILES_NUM_OFFSET 4
332 /* NWK Commands - Discovery Request - Device Types */
333 #define RF4CE_DEVICE_RESERVED_INVALID 0x00
334 #define RF4CE_DEVICE_REMOTE_CONTROL 0x01
335 #define RF4CE_DEVICE_TELEVISION 0x02
336 #define RF4CE_DEVICE_PROJECTOR 0x03
337 #define RF4CE_DEVICE_PLAYER 0x04
338 #define RF4CE_DEVICE_RECORDER 0x05
339 #define RF4CE_DEVICE_VIDEO_PLAYER_RECORDER 0x06
340 #define RF4CE_DEVICE_AUDIO_PLAYER_RECORDER 0x07
341 #define RF4CE_DEVICE_AUDIO_VIDEO_RECORDER 0x08
342 #define RF4CE_DEVICE_SET_TOP_BOX 0x09
343 #define RF4CE_DEVICE_HOME_THEATER_SYSTEM 0x0a
344 #define RF4CE_DEVICE_MEDIA_CENTER_PC 0x0b
345 #define RF4CE_DEVICE_GAME_CONSOLE 0x0c
346 #define RF4CE_DEVICE_SATELLITE_RADIO_RECEIVER 0x0d
347 #define RF4CE_DEVICE_IR_EXTENDER 0x0e
348 #define RF4CE_DEVICE_MONITOR 0x0f
349 #define RF4CE_DEVICE_ALL_DEVICES 0xff
351 static const value_string rf4ce_nwk_device_type_vals
[] = {
352 { RF4CE_DEVICE_RESERVED_INVALID
, "Invalid" },
353 { RF4CE_DEVICE_REMOTE_CONTROL
, "Remote Control" },
354 { RF4CE_DEVICE_TELEVISION
, "Television" },
355 { RF4CE_DEVICE_PROJECTOR
, "Projector" },
356 { RF4CE_DEVICE_PLAYER
, "Player" },
357 { RF4CE_DEVICE_RECORDER
, "Recorder" },
358 { RF4CE_DEVICE_VIDEO_PLAYER_RECORDER
, "Video Player Recorder" },
359 { RF4CE_DEVICE_AUDIO_PLAYER_RECORDER
, "Audio Player Recorder" },
360 { RF4CE_DEVICE_AUDIO_VIDEO_RECORDER
, "Audio Video Recorder" },
361 { RF4CE_DEVICE_SET_TOP_BOX
, "Set Top Box" },
362 { RF4CE_DEVICE_HOME_THEATER_SYSTEM
, "Home Theater System" },
363 { RF4CE_DEVICE_MEDIA_CENTER_PC
, "Media Center PC" },
364 { RF4CE_DEVICE_GAME_CONSOLE
, "Game Console" },
365 { RF4CE_DEVICE_SATELLITE_RADIO_RECEIVER
, "Satellite Radio Receiver" },
366 { RF4CE_DEVICE_IR_EXTENDER
, "IR Extender" },
367 { RF4CE_DEVICE_MONITOR
, "Monitor" },
368 { RF4CE_DEVICE_ALL_DEVICES
, "All the Devices" },
372 #define RF4CE_NWK_STATUS_SUCCESS 0x00
373 #define RF4CE_NWK_STATUS_NO_ORG_CAPACITY 0xb0
374 #define RF4CE_NWK_STATUS_NO_REC_CAPACITY 0xb1
375 #define RF4CE_NWK_STATUS_NO_PAIRING 0xb2
376 #define RF4CE_NWK_STATUS_NO_RESPONSE 0xb3
377 #define RF4CE_NWK_STATUS_NOT_PERMITTED 0xb4
378 #define RF4CE_NWK_STATUS_DUPLICATE_PAIRING 0xb5
379 #define RF4CE_NWK_STATUS_FRAME_COUNTER_EXPIRED 0xb6
380 #define RF4CE_NWK_STATUS_DISCOVERY_ERROR 0xb7
381 #define RF4CE_NWK_STATUS_DISCOVERY_TIMEOUT 0xb8
382 #define RF4CE_NWK_STATUS_SECURITY_TIMEOUT 0xb9
383 #define RF4CE_NWK_STATUS_SECURITY_FAILURE 0xba
384 #define RF4CE_NWK_STATUS_INVALID_PARAMETER 0xe8
385 #define RF4CE_NWK_STATUS_UNSUPPORTED_ATTRIBUTE 0xf4
386 #define RF4CE_NWK_STATUS_INVALID_INDEX 0xf9
388 static const value_string rf4ce_nwk_disc_status_vals
[] = {
389 { RF4CE_NWK_STATUS_SUCCESS
, "Success" },
390 { RF4CE_NWK_STATUS_NO_ORG_CAPACITY
, "No Org Capacity" },
391 { RF4CE_NWK_STATUS_NO_REC_CAPACITY
, "No Rec Capacity" },
392 { RF4CE_NWK_STATUS_NO_PAIRING
, "No Pairing" },
393 { RF4CE_NWK_STATUS_NO_RESPONSE
, "No Response" },
394 { RF4CE_NWK_STATUS_NOT_PERMITTED
, "Not Permitted" },
395 { RF4CE_NWK_STATUS_DUPLICATE_PAIRING
, "Duplicate Pairing" },
396 { RF4CE_NWK_STATUS_FRAME_COUNTER_EXPIRED
, "Frame Counter Expired" },
397 { RF4CE_NWK_STATUS_DISCOVERY_ERROR
, "Discovery Error" },
398 { RF4CE_NWK_STATUS_DISCOVERY_TIMEOUT
, "Discovery Timeout" },
399 { RF4CE_NWK_STATUS_SECURITY_TIMEOUT
, "Security Timeout" },
400 { RF4CE_NWK_STATUS_SECURITY_FAILURE
, "Security Failure" },
401 { RF4CE_NWK_STATUS_INVALID_PARAMETER
, "Invalid Parameter" },
402 { RF4CE_NWK_STATUS_UNSUPPORTED_ATTRIBUTE
, "Unsupported Attribute" },
403 { RF4CE_NWK_STATUS_INVALID_INDEX
, "Invalid Index" },
407 static bool dissect_rf4ce_nwk_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
);
409 /* RF4CE NWK commands dissectors */
410 static int dissect_rf4ce_nwk_common(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
);
412 static void dissect_rf4ce_nwk_cmd(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int *offset
);
414 static void dissect_rf4ce_nwk_common_node_capabilities(tvbuff_t
*tvb
, proto_tree
*tree
, int *offset
);
415 static void dissect_rf4ce_nwk_common_vendor_info(tvbuff_t
*tvb
, proto_tree
*tree
, int *offset
);
416 static void dissect_rf4ce_nwk_common_app_capabilities(tvbuff_t
*tvb
, proto_tree
*tree
, int *offset
, uint8_t parsing_mask
);
417 static void dissect_rf4ce_nwk_disc_resp_class_descriptor(tvbuff_t
*tvb
, proto_tree
*tree
, int *offset
, int hf
);
419 static void dissect_rf4ce_nwk_cmd_disc_req(tvbuff_t
*tvb
, proto_tree
*tree
, int *offset
);
420 static void dissect_rf4ce_nwk_cmd_disc_rsp(tvbuff_t
*tvb
, proto_tree
*tree
, int *offset
);
422 static void dissect_rf4ce_nwk_cmd_pair_req(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int *offset
);
423 static void dissect_rf4ce_nwk_cmd_pair_rsp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int *offset
);
425 static void dissect_rf4ce_nwk_cmd_key_seed(tvbuff_t
*tvb
, proto_tree
*tree
, int *offset
);
427 static void dissect_rf4ce_nwk_cmd_ping(tvbuff_t
*tvb
, proto_tree
*tree
, int *offset
);
429 static void rf4ce_cleanup(void)
431 rf4ce_secur_cleanup();
434 static void *uat_sec_record_copy_cb(void *n
, const void *o
, size_t siz _U_
)
436 uat_security_record_t
*new_sec_rec
= (uat_security_record_t
*)n
;
437 const uat_security_record_t
*old_sec_rec
= (const uat_security_record_t
*)o
;
439 new_sec_rec
->sec_str
= g_strdup(old_sec_rec
->sec_str
);
440 new_sec_rec
->type
= old_sec_rec
->type
;
441 new_sec_rec
->label
= g_strdup(old_sec_rec
->label
);
446 static bool rf4ce_security_parse_sec_str(const char *data_str
, uint8_t *dst_buf
)
450 bool string_mode
= false;
452 if (data_str
== NULL
|| dst_buf
== NULL
)
458 memset(dst_buf
, 0, SEC_STR_LEN
);
461 * Attempt to parse the key string. The key string must
462 * be at least 16 pairs of hexidecimal digits with the
463 * following optional separators: ':', '-', " ", or 16
464 * alphanumeric characters after a double-quote.
474 for (i
= SEC_STR_LEN
- 1; i
>= 0; i
--)
478 if (g_ascii_isprint(temp
))
490 /* If this character is a separator, skip it. */
491 if ((temp
== ':') || (temp
== '-') || (temp
== ' '))
493 temp
= *(data_str
++);
496 /* Process a nibble. */
497 if (g_ascii_isxdigit(temp
))
499 dst_buf
[j
] = g_ascii_xdigit_value(temp
) << 4;
506 /* Get the next nibble. */
507 temp
= *(data_str
++);
509 /* Process another nibble. */
510 if (g_ascii_isxdigit(temp
))
512 dst_buf
[j
] |= g_ascii_xdigit_value(temp
);
519 /* Get the next nibble. */
520 temp
= *(data_str
++);
526 /* If we get this far, then the key was good. */
530 static bool uat_sec_record_update_cb(void *r
, char **err
)
532 uat_security_record_t
*rec
= (uat_security_record_t
*)r
;
533 uint8_t sec_str
[SEC_STR_LEN
] = {0};
535 if (rec
->sec_str
== NULL
)
537 *err
= g_strdup("Data field can't be blank");
541 g_strstrip(rec
->sec_str
);
543 if (rf4ce_security_parse_sec_str(rec
->sec_str
, sec_str
))
547 if (rec
->type
== RF4CE_SEC_STR_TYPE_NWK_KEY
)
549 nwk_key_storage_add_entry(
551 NULL
, /* controller addr */
552 NULL
, /* target addr */
553 true, /* key from GUI */
554 false /* packet number */);
556 vendor_secret_storage_release_entry(sec_str
);
560 vendor_secret_storage_add_entry(sec_str
);
561 nwk_key_storage_release_entry(sec_str
, true /* key from GUI */);
566 *err
= ws_strdup_printf(
567 "Expecting %d hexadecimal bytes or a %d character double-quoted string", SEC_STR_LEN
, SEC_STR_LEN
);
574 static void uat_sec_record_free_cb(void *r
)
576 uat_security_record_t
*sec_record
= (uat_security_record_t
*)r
;
577 uint8_t sec_str
[SEC_STR_LEN
];
579 if (rf4ce_security_parse_sec_str(sec_record
->sec_str
, sec_str
))
581 if (sec_record
->type
== RF4CE_SEC_STR_TYPE_NWK_KEY
)
583 nwk_key_storage_release_entry(sec_str
, true /* key from GUI */);
587 vendor_secret_storage_release_entry(sec_str
);
591 g_free(sec_record
->sec_str
);
592 g_free(sec_record
->label
);
595 static void uat_sec_record_post_update(void)
597 uint8_t sec_str
[SEC_STR_LEN
];
599 vendor_secret_storage_add_entry(DEFAULT_SECRET
);
601 /* Load the pre-configured slist from the UAT. */
602 for (unsigned i
= 0; (uat_security_records
) && (i
< num_uat_security_records
); i
++)
604 if (rf4ce_security_parse_sec_str(uat_security_records
[i
].sec_str
, sec_str
))
606 if (uat_security_records
[i
].type
== RF4CE_SEC_STR_TYPE_NWK_KEY
)
608 nwk_key_storage_add_entry(
610 NULL
, /* controller addr */
611 NULL
, /* target addr */
612 true, /* key from GUI */
613 false /* packet number */);
615 vendor_secret_storage_release_entry(sec_str
);
619 vendor_secret_storage_add_entry(sec_str
);
620 nwk_key_storage_release_entry(sec_str
, true /* key from GUI */);
626 static bool dissect_rf4ce_nwk_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
628 unsigned reported_length
= tvb_reported_length(tvb
);
629 unsigned length
= tvb_captured_length(tvb
);
632 uint8_t security_enabled
;
638 if (reported_length
>= RF4CE_MIN_NWK_LENGTH
&& reported_length
<= RF4CE_MAX_NWK_LENGTH
)
640 if (length
< RF4CE_MIN_NWK_LENGTH
)
644 fcf
= tvb_get_uint8(tvb
, 0);
645 frame_type
= fcf
& RF4CE_NWK_FCF_FRAME_TYPE_MASK
;
646 security_enabled
= fcf
& RF4CE_NWK_FCF_SECURITY_MASK
;
647 reserved
= (fcf
& RF4CE_NWK_FCF_RESERVED_MASK
) >> 5;
651 case RF4CE_NWK_FCF_FRAME_TYPE_DATA
:
652 case RF4CE_NWK_FCF_FRAME_TYPE_CMD
:
653 case RF4CE_NWK_FCF_FRAME_TYPE_VENDOR_SPECIFIC
:
654 /* Accepted frame types */
660 /* Reserved value must be 1 */
665 if((frame_type
== RF4CE_NWK_FCF_FRAME_TYPE_DATA
) || (frame_type
== RF4CE_NWK_FCF_FRAME_TYPE_VENDOR_SPECIFIC
))
671 profile_id
= tvb_get_uint8(tvb
, 5);
672 if ((profile_id
>= 0x04) && (profile_id
<= 0xbf))
676 if (frame_type
== RF4CE_NWK_FCF_FRAME_TYPE_VENDOR_SPECIFIC
)
682 vendor_id
= tvb_get_letohs(tvb
, 6);
685 case RF4CE_VENDOR_ID_PANASONIC
:
686 case RF4CE_VENDOR_ID_SONY
:
687 case RF4CE_VENDOR_ID_SAMSUNG
:
688 case RF4CE_VENDOR_ID_PHILIPS
:
689 case RF4CE_VENDOR_ID_FREESCALE
:
690 case RF4CE_VENDOR_ID_OKI
:
691 case RF4CE_VENDOR_ID_TEXAS_INSTRUMENTS
:
692 case RF4CE_VENDOR_ID_TEST_1
:
693 case RF4CE_VENDOR_ID_TEST_2
:
694 case RF4CE_VENDOR_ID_TEST_3
:
695 /* Allowed vendor IDs */
703 else if(frame_type
== RF4CE_NWK_FCF_FRAME_TYPE_CMD
)
709 /* If security is enabled, the command ID will be encrypted */
710 if (!security_enabled
)
712 command_id
= tvb_get_uint8(tvb
, 5);
715 case RF4CE_NWK_CMD_DISCOVERY_REQ
:
716 case RF4CE_NWK_CMD_DISCOVERY_RSP
:
717 case RF4CE_NWK_CMD_PAIR_REQ
:
718 case RF4CE_NWK_CMD_PAIR_RSP
:
719 case RF4CE_NWK_CMD_UNPAIR_REQ
:
720 case RF4CE_NWK_CMD_KEY_SEED
:
721 case RF4CE_NWK_CMD_PING_REQ
:
722 case RF4CE_NWK_CMD_PING_RSP
:
723 /* Allowed command IDs */
731 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "RF4CE NWK");
732 col_clear(pinfo
->cinfo
, COL_INFO
);
734 dissect_rf4ce_nwk_common(tvb
, pinfo
, tree
, data
);
741 static int dissect_rf4ce_nwk_common(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
745 uint8_t *decrypted
= (uint8_t *)wmem_alloc(pinfo
->pool
, 512);
746 uint8_t src_addr
[RF4CE_IEEE_ADDR_LEN
] = {0};
747 uint8_t dst_addr
[RF4CE_IEEE_ADDR_LEN
] = {0};
750 uint8_t frame_type
= 0xff;
751 uint8_t profile_id
= 0xff;
754 proto_item
*ti
= proto_tree_add_item(tree
, proto_rf4ce_nwk
, tvb
, 0, -1, ENC_LITTLE_ENDIAN
);
755 proto_tree
*rf4ce_nwk_tree
= proto_item_add_subtree(ti
, ett_rf4ce_nwk
);
757 static int *const nwk_fcf_bits
[] = {
758 &hf_rf4ce_nwk_fcf_frame_type
,
759 &hf_rf4ce_nwk_fcf_security_enabled
,
760 &hf_rf4ce_nwk_fcf_protocol_version
,
761 &hf_rf4ce_nwk_fcf_reserved
,
762 &hf_rf4ce_nwk_fcf_channel_designator
,
765 proto_tree_add_bitmask(rf4ce_nwk_tree
, tvb
, offset
, hf_rf4ce_nwk_fcf
, ett_rf4ce_nwk
, nwk_fcf_bits
, ENC_LITTLE_ENDIAN
);
766 fcf
= tvb_get_uint8(tvb
, offset
);
769 proto_tree_add_item(rf4ce_nwk_tree
, hf_rf4ce_nwk_seq_num
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
772 frame_type
= fcf
& RF4CE_NWK_FCF_FRAME_TYPE_MASK
;
774 if (frame_type
== RF4CE_NWK_FCF_FRAME_TYPE_DATA
|| frame_type
== RF4CE_NWK_FCF_FRAME_TYPE_VENDOR_SPECIFIC
)
776 proto_tree_add_item(rf4ce_nwk_tree
, hf_rf4ce_nwk_profile_id
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
777 profile_id
= tvb_get_uint8(tvb
, offset
);
781 if (frame_type
== RF4CE_NWK_FCF_FRAME_TYPE_VENDOR_SPECIFIC
)
783 proto_tree_add_item(rf4ce_nwk_tree
, hf_rf4ce_nwk_vendor_id
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
787 rf4ce_addr_table_get_ieee_addr(src_addr
, pinfo
, true);
788 rf4ce_addr_table_get_ieee_addr(dst_addr
, pinfo
, false);
790 size
= tvb_captured_length_remaining(tvb
, 0);
792 if (fcf
& RF4CE_NWK_FCF_SECURITY_MASK
)
794 success
= decrypt_data(
795 tvb_get_ptr(tvb
, 0, size
),
802 else if (size
> offset
)
805 tvb_memcpy(tvb
, decrypted
, offset
, size
);
815 unsigned decrypted_offset
= 0;
817 /* On decryption success: replace the tvb, make offset point to its beginning */
818 tvb
= tvb_new_child_real_data(tvb
, decrypted
, size
, size
);
819 add_new_data_source(pinfo
, tvb
, "CCM* decrypted payload");
821 if (frame_type
== RF4CE_NWK_FCF_FRAME_TYPE_CMD
)
823 proto_tree
*nwk_payload_tree
= proto_tree_add_subtree(rf4ce_nwk_tree
, tvb
, decrypted_offset
, tvb_captured_length(tvb
) - decrypted_offset
, ett_rf4ce_nwk_payload
, NULL
, "NWK Payload");
824 dissect_rf4ce_nwk_cmd(tvb
, pinfo
, nwk_payload_tree
, &decrypted_offset
);
826 else if (frame_type
== RF4CE_NWK_FCF_FRAME_TYPE_DATA
)
828 if (profile_id
== RF4CE_NWK_PROFILE_ID_GDP
)
830 decrypted_offset
+= call_dissector_with_data(rf4ce_gdp_handle
, tvb
, pinfo
, tree
, (void *)("GDP"));
832 else if (profile_id
== RF4CE_NWK_PROFILE_ID_ZRC20
)
834 decrypted_offset
+= call_dissector_with_data(rf4ce_gdp_handle
, tvb
, pinfo
, tree
, (void *)("ZRC 2.0"));
836 else if (profile_id
== RF4CE_NWK_PROFILE_ID_ZRC10
)
838 decrypted_offset
+= call_dissector_with_data(rf4ce_gdp_handle
, tvb
, pinfo
, tree
, (void *)("ZRC 1.0"));
842 offset
+= decrypted_offset
;
846 /* On decryption error: make offset point to the end of original tvb */
847 offset
= tvb_reported_length(tvb
);
850 if (offset
< tvb_captured_length(tvb
))
852 unsigned unparsed_length
= tvb_captured_length(tvb
) - offset
;
853 proto_tree_add_item(rf4ce_nwk_tree
, hf_rf4ce_nwk_unparsed_payload
, tvb
, offset
, unparsed_length
, ENC_NA
);
855 /* enable this block if you need to add NWK MIC */
856 offset
+= unparsed_length
;
861 if (fcf
& RF4CE_NWK_FCF_SECURITY_MASK
)
863 proto_tree_add_item(rf4ce_nwk_tree
, hf_rf4ce_nwk_mic
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
868 return tvb_captured_length(tvb
);
871 static void dissect_rf4ce_nwk_cmd(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int *offset
)
873 int cmd_id
= tvb_get_uint8(tvb
, *offset
);
875 proto_tree_add_item(tree
, hf_rf4ce_nwk_cmd_id
, tvb
, *offset
, 1, ENC_LITTLE_ENDIAN
);
878 col_set_str(pinfo
->cinfo
, COL_INFO
, val_to_str_const(cmd_id
, rf4ce_nwk_cmd_names
, "Unknown Command"));
882 case RF4CE_NWK_CMD_DISCOVERY_REQ
:
883 dissect_rf4ce_nwk_cmd_disc_req(tvb
, tree
, offset
);
886 case RF4CE_NWK_CMD_DISCOVERY_RSP
:
887 dissect_rf4ce_nwk_cmd_disc_rsp(tvb
, tree
, offset
);
890 case RF4CE_NWK_CMD_PAIR_REQ
:
891 dissect_rf4ce_nwk_cmd_pair_req(tvb
, pinfo
, tree
, offset
);
894 case RF4CE_NWK_CMD_PAIR_RSP
:
895 dissect_rf4ce_nwk_cmd_pair_rsp(tvb
, pinfo
, tree
, offset
);
898 case RF4CE_NWK_CMD_UNPAIR_REQ
:
901 case RF4CE_NWK_CMD_KEY_SEED
:
902 dissect_rf4ce_nwk_cmd_key_seed(tvb
, tree
, offset
);
905 case RF4CE_NWK_CMD_PING_REQ
:
906 dissect_rf4ce_nwk_cmd_ping(tvb
, tree
, offset
);
909 case RF4CE_NWK_CMD_PING_RSP
:
910 dissect_rf4ce_nwk_cmd_ping(tvb
, tree
, offset
);
915 static void dissect_rf4ce_nwk_common_node_capabilities(tvbuff_t
*tvb
, proto_tree
*tree
, int *offset
)
917 static int *const nwk_node_capabilities_bits
[] = {
918 &hf_rf4ce_nwk_node_capabilities_node_type
,
919 &hf_rf4ce_nwk_node_capabilities_power_source
,
920 &hf_rf4ce_nwk_node_capabilities_security
,
921 &hf_rf4ce_nwk_node_capabilities_channel_normalization
,
922 &hf_rf4ce_nwk_node_capabilities_reserved
,
925 proto_tree_add_bitmask(tree
, tvb
, *offset
, hf_rf4ce_nwk_node_capabilities
, ett_rf4ce_nwk
, nwk_node_capabilities_bits
, ENC_LITTLE_ENDIAN
);
929 static void dissect_rf4ce_nwk_common_vendor_info(tvbuff_t
*tvb
, proto_tree
*tree
, int *offset
)
931 proto_tree
*vendor_info_tree
= proto_tree_add_subtree(tree
, tvb
, *offset
, tvb_captured_length(tvb
) - *offset
, ett_rf4ce_nwk_vendor_info
, NULL
, "Vendor Information Fields");
933 proto_tree_add_item(vendor_info_tree
, hf_rf4ce_nwk_disc_req_vendor_id
, tvb
, *offset
, 2, ENC_LITTLE_ENDIAN
);
936 proto_tree_add_item(vendor_info_tree
, hf_rf4ce_nwk_vendor_string
, tvb
, *offset
, RF4CE_NWK_VENDOR_STRING_MAX_LENGTH
, ENC_UTF_8
);
937 *offset
+= RF4CE_NWK_VENDOR_STRING_MAX_LENGTH
;
940 static void dissect_rf4ce_nwk_common_app_capabilities(tvbuff_t
*tvb
, proto_tree
*tree
, int *offset
, uint8_t parsing_mask
)
942 int nwk_app_capabilities
= 0;
943 int supported_devices_num
= 0;
944 int supported_profiles_num
= 0;
946 static int *const nwk_app_capabilities_bits
[] = {
947 &hf_rf4ce_nwk_app_capabilities_usr_str
,
948 &hf_rf4ce_nwk_app_capabilities_supported_dev_num
,
949 &hf_rf4ce_nwk_app_capabilities_reserved1
,
950 &hf_rf4ce_nwk_app_capabilities_supported_profiles_num
,
951 &hf_rf4ce_nwk_app_capabilities_reserved2
,
954 proto_tree_add_bitmask(tree
, tvb
, *offset
, hf_rf4ce_nwk_app_capabilities
, ett_rf4ce_nwk
, nwk_app_capabilities_bits
, ENC_LITTLE_ENDIAN
);
955 nwk_app_capabilities
= tvb_get_uint8(tvb
, *offset
);
958 if (nwk_app_capabilities
& RF4CE_NWK_USR_STR_SPECIFIED_MASK
)
960 if (parsing_mask
& RF4CE_NWK_USR_STR_PARSING_MASK_DISC_RESP
)
962 proto_tree
*usr_str_tree
= proto_tree_add_subtree(tree
, tvb
, *offset
, RF4CE_NWK_USR_STR_LENGTH
, ett_rf4ce_nwk_usr_str
, NULL
, "Extra Status Information");
964 proto_tree_add_item(usr_str_tree
, hf_rf4ce_nwk_usr_str_disc_rsp_app_usr_str
, tvb
, *offset
, RF4CE_NWK_USR_STR_DISC_RSP_APP_USR_STR_LENGTH
, ENC_UTF_8
);
965 /* -1: to show the NULL-terminator byte in a tree */
966 *offset
+= RF4CE_NWK_USR_STR_DISC_RSP_APP_USR_STR_LENGTH
- 1;
968 proto_tree_add_item(usr_str_tree
, hf_rf4ce_nwk_usr_str_disc_rsp_null
, tvb
, *offset
, 1, ENC_LITTLE_ENDIAN
);
971 proto_tree_add_item(usr_str_tree
, hf_rf4ce_nwk_usr_str_disc_rsp_reserved
, tvb
, *offset
, 2, ENC_LITTLE_ENDIAN
);
974 dissect_rf4ce_nwk_disc_resp_class_descriptor(tvb
, usr_str_tree
, offset
, hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_tertiary
);
975 dissect_rf4ce_nwk_disc_resp_class_descriptor(tvb
, usr_str_tree
, offset
, hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_secondary
);
976 dissect_rf4ce_nwk_disc_resp_class_descriptor(tvb
, usr_str_tree
, offset
, hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_primary
);
978 proto_tree_add_item(usr_str_tree
, hf_rf4ce_nwk_usr_str_disc_rsp_discovery_lqi_threshold
, tvb
, *offset
, 1, ENC_LITTLE_ENDIAN
);
983 proto_tree_add_item(tree
, hf_rf4ce_nwk_usr_str
, tvb
, *offset
, RF4CE_NWK_USR_STR_LENGTH
, ENC_NA
);
984 *offset
+= RF4CE_NWK_USR_STR_LENGTH
;
988 supported_devices_num
= ((nwk_app_capabilities
& RF4CE_NWK_SUPPORTED_DEV_NUM_MASK
) >> RF4CE_NWK_SUPPORTED_DEV_NUM_OFFSET
);
989 if (supported_devices_num
> 0)
991 proto_tree
*dev_type_tree
= proto_tree_add_subtree(tree
, tvb
, *offset
, supported_devices_num
, ett_rf4ce_nwk_dev_types_list
, NULL
, "Device Type List");
993 for (int i
= 0; i
< supported_devices_num
; i
++)
995 proto_tree_add_item(dev_type_tree
, hf_rf4ce_nwk_app_cap_dev_type
, tvb
, *offset
, 1, ENC_LITTLE_ENDIAN
);
1000 supported_profiles_num
= ((nwk_app_capabilities
& RF4CE_NWK_SUPPORTED_PROFILES_NUM_MASK
) >> RF4CE_NWK_SUPPORTED_PROFILES_NUM_OFFSET
);
1001 if (supported_profiles_num
> 0)
1003 proto_tree
*profiles_tree
= proto_tree_add_subtree(tree
, tvb
, *offset
, supported_profiles_num
, ett_rf4ce_nwk_profiles_list
, NULL
, "Profiles ID List");
1005 for (int i
= 0; i
< supported_profiles_num
; i
++)
1007 proto_tree_add_item(profiles_tree
, hf_rf4ce_nwk_app_cap_profile_id
, tvb
, *offset
, 1, ENC_LITTLE_ENDIAN
);
1013 static void dissect_rf4ce_nwk_disc_resp_class_descriptor(tvbuff_t
*tvb
, proto_tree
*tree
, int *offset
, int hf
)
1015 static int *const class_num_bits
[] = {
1016 &hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_class_num
,
1017 &hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_duplicate_class_num_handling
,
1018 &hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_reserved
,
1021 proto_tree_add_bitmask(tree
, tvb
, *offset
, hf
, ett_rf4ce_nwk_usr_str_class_descriptor
, class_num_bits
, ENC_LITTLE_ENDIAN
);
1025 static void dissect_rf4ce_nwk_cmd_disc_req(tvbuff_t
*tvb
, proto_tree
*tree
, int *offset
)
1027 dissect_rf4ce_nwk_common_node_capabilities(tvb
, tree
, offset
);
1028 dissect_rf4ce_nwk_common_vendor_info(tvb
, tree
, offset
);
1029 dissect_rf4ce_nwk_common_app_capabilities(tvb
, tree
, offset
, RF4CE_NWK_USR_STR_PARSING_MASK_NONE
);
1031 proto_tree_add_item(tree
, hf_rf4ce_nwk_requested_dev_type
, tvb
, *offset
, 1, ENC_LITTLE_ENDIAN
);
1035 static void dissect_rf4ce_nwk_cmd_disc_rsp(tvbuff_t
*tvb
, proto_tree
*tree
, int *offset
)
1037 proto_tree_add_item(tree
, hf_rf4ce_nwk_disc_resp_status
, tvb
, *offset
, 1, ENC_LITTLE_ENDIAN
);
1040 dissect_rf4ce_nwk_common_node_capabilities(tvb
, tree
, offset
);
1041 dissect_rf4ce_nwk_common_vendor_info(tvb
, tree
, offset
);
1042 dissect_rf4ce_nwk_common_app_capabilities(tvb
, tree
, offset
, RF4CE_NWK_USR_STR_PARSING_MASK_DISC_RESP
);
1044 proto_tree_add_item(tree
, hf_rf4ce_nwk_disc_resp_lqi
, tvb
, *offset
, 1, ENC_LITTLE_ENDIAN
);
1048 static void dissect_rf4ce_nwk_cmd_pair_req(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int *offset
)
1050 uint8_t expected_transfer_count
;
1052 proto_tree_add_item(tree
, hf_rf4ce_nwk_pair_req_nwk_addr
, tvb
, *offset
, 2, ENC_LITTLE_ENDIAN
);
1055 dissect_rf4ce_nwk_common_node_capabilities(tvb
, tree
, offset
);
1056 dissect_rf4ce_nwk_common_vendor_info(tvb
, tree
, offset
);
1057 dissect_rf4ce_nwk_common_app_capabilities(tvb
, tree
, offset
, RF4CE_NWK_USR_STR_PARSING_MASK_NONE
);
1059 proto_tree_add_item(tree
, hf_rf4ce_nwk_pair_req_key_exch_num
, tvb
, *offset
, 1, ENC_LITTLE_ENDIAN
);
1061 expected_transfer_count
= tvb_get_uint8(tvb
, *offset
) + 1;
1062 keypair_context_init((const uint8_t *)pinfo
->dl_src
.data
, (const uint8_t *)pinfo
->dl_dst
.data
, expected_transfer_count
);
1066 static void dissect_rf4ce_nwk_cmd_pair_rsp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int *offset
)
1068 uint16_t allocated_nwk_addr
;
1071 proto_tree_add_item(tree
, hf_rf4ce_nwk_pair_rsp_status
, tvb
, *offset
, 1, ENC_LITTLE_ENDIAN
);
1074 proto_tree_add_item(tree
, hf_rf4ce_nwk_pair_rsp_allocated_nwk_addr
, tvb
, *offset
, 2, ENC_LITTLE_ENDIAN
);
1075 allocated_nwk_addr
= tvb_get_uint16(tvb
, *offset
, ENC_LITTLE_ENDIAN
);
1078 proto_tree_add_item(tree
, hf_rf4ce_nwk_pair_rsp_nwk_addr
, tvb
, *offset
, 2, ENC_LITTLE_ENDIAN
);
1079 nwk_addr
= tvb_get_uint16(tvb
, *offset
, ENC_LITTLE_ENDIAN
);
1082 dissect_rf4ce_nwk_common_node_capabilities(tvb
, tree
, offset
);
1083 dissect_rf4ce_nwk_common_vendor_info(tvb
, tree
, offset
);
1084 dissect_rf4ce_nwk_common_app_capabilities(tvb
, tree
, offset
, RF4CE_NWK_USR_STR_PARSING_MASK_NONE
);
1086 rf4ce_addr_table_add_addrs(pinfo
->dl_dst
.data
, allocated_nwk_addr
);
1087 rf4ce_addr_table_add_addrs(pinfo
->dl_src
.data
, nwk_addr
);
1090 static void dissect_rf4ce_nwk_cmd_key_seed(tvbuff_t
*tvb
, proto_tree
*tree
, int *offset
)
1092 uint8_t seed_data
[RF4CE_NWK_KEY_SEED_DATA_LENGTH
] = {0};
1093 uint8_t seed_seq_num
= 0;
1095 proto_tree_add_item(tree
, hf_rf4ce_nwk_seed_seq_num
, tvb
, *offset
, 1, ENC_LITTLE_ENDIAN
);
1096 seed_seq_num
= tvb_get_uint8(tvb
, *offset
);
1099 proto_tree_add_item(tree
, hf_rf4ce_nwk_seed_data
, tvb
, *offset
, RF4CE_NWK_KEY_SEED_DATA_LENGTH
, ENC_NA
);
1100 tvb_memcpy(tvb
, (void *)seed_data
, *offset
, RF4CE_NWK_KEY_SEED_DATA_LENGTH
);
1101 *offset
+= RF4CE_NWK_KEY_SEED_DATA_LENGTH
;
1103 keypair_context_update_seed(seed_data
, seed_seq_num
);
1106 static void dissect_rf4ce_nwk_cmd_ping(tvbuff_t
*tvb
, proto_tree
*tree
, int *offset
)
1108 proto_tree_add_item(tree
, hf_rf4ce_nwk_ping_options
, tvb
, *offset
, 1, ENC_LITTLE_ENDIAN
);
1111 proto_tree_add_item(tree
, hf_rf4ce_nwk_ping_payload
, tvb
, *offset
, 4, ENC_LITTLE_ENDIAN
);
1115 void proto_register_rf4ce_nwk(void)
1117 static hf_register_info hf
[] = {
1119 {"Frame Control Field", "rf4ce-nwk.fcf",
1123 {&hf_rf4ce_nwk_fcf_frame_type
,
1124 {"Frame Type", "rf4ce-nwk.fcf.frame_type",
1126 VALS(rf4ce_nwk_frame_types
), RF4CE_NWK_FCF_FRAME_TYPE_MASK
,
1128 {&hf_rf4ce_nwk_fcf_security_enabled
,
1129 {"Security enabled", "rf4ce-nwk.fcf.security_enabled",
1131 TFS(&tfs_yes_no
), RF4CE_NWK_FCF_SECURITY_MASK
,
1133 {&hf_rf4ce_nwk_fcf_protocol_version
,
1134 {"Protocol version", "rf4ce-nwk.fcf.protocol_version",
1136 NULL
, RF4CE_NWK_FCF_PROTOCOL_VERSION_MASK
,
1138 {&hf_rf4ce_nwk_fcf_reserved
,
1139 {"Reserved", "rf4ce-nwk.fcf.reserved",
1141 NULL
, RF4CE_NWK_FCF_RESERVED_MASK
,
1143 {&hf_rf4ce_nwk_fcf_channel_designator
,
1144 {"Channel designator", "rf4ce-nwk.fcf.channel_designator",
1146 VALS(rf4ce_nwk_channel_designators
), RF4CE_NWK_FCF_CHANNEL_DESIGNATOR_MASK
,
1148 {&hf_rf4ce_nwk_seq_num
,
1149 {"Sequence number", "rf4ce-nwk.seqn",
1150 FT_UINT32
, BASE_DEC
,
1153 {&hf_rf4ce_nwk_profile_id
,
1154 {"Profile ID", "rf4ce-nwk.profile_id",
1156 VALS(rf4ce_nwk_profile_ids
), 0x0,
1158 {&hf_rf4ce_nwk_vendor_id
,
1159 {"Vendor ID", "rf4ce-nwk.vendor_id",
1160 FT_UINT16
, BASE_HEX
,
1163 {&hf_rf4ce_nwk_cmd_id
,
1164 {"Command ID", "rf4ce-nwk.cmd_id",
1166 VALS(rf4ce_nwk_cmd_names
), 0x0,
1168 {&hf_rf4ce_nwk_node_capabilities
,
1169 {"Node Capabilities", "rf4ce-nwk.node_capabilities",
1173 {&hf_rf4ce_nwk_node_capabilities_node_type
,
1174 {"Node Type", "rf4ce-nwk.node_capabilities.node_type",
1176 VALS(rf4ce_nwk_node_types
), RF4CE_NWK_NODE_TYPE_MASK
,
1178 {&hf_rf4ce_nwk_node_capabilities_power_source
,
1179 {"Power Source", "rf4ce-nwk.node_capabilities.power_source",
1181 VALS(rf4ce_nwk_power_sources
), RF4CE_NWK_POWER_SOURCE_MASK
,
1183 {&hf_rf4ce_nwk_node_capabilities_security
,
1184 {"Security Capable", "rf4ce-nwk.node_capabilities.security",
1186 TFS(&tfs_yes_no
), RF4CE_NWK_SECURITY_MASK
,
1188 {&hf_rf4ce_nwk_node_capabilities_channel_normalization
,
1189 {"Channel Normalization", "rf4ce-nwk.node_capabilities.channel_normalization",
1191 TFS(&tfs_yes_no
), RF4CE_NWK_CHANNEL_NORMALIZATION_MASK
,
1193 {&hf_rf4ce_nwk_node_capabilities_reserved
,
1194 {"Reserved", "rf4ce-nwk.node_capabilities.reserved",
1196 NULL
, RF4CE_NWK_RESERVED_MASK
,
1198 {&hf_rf4ce_nwk_disc_req_vendor_id
,
1199 {"Vendor ID", "rf4ce-nwk.disc_req.vendor_id",
1200 FT_UINT16
, BASE_HEX
,
1201 VALS(rf4ce_disc_req_vendor_ids
), 0x0,
1203 {&hf_rf4ce_nwk_vendor_string
,
1204 {"Vendor String", "rf4ce-nwk.disc_req.vendor_str",
1205 FT_STRING
, BASE_NONE
,
1208 {&hf_rf4ce_nwk_app_capabilities
,
1209 {"App Capabilities", "rf4ce-nwk.app_capabilities",
1213 {&hf_rf4ce_nwk_app_capabilities_usr_str
,
1214 {"User String Specified", "rf4ce-nwk.app_capabilities.usr_str",
1216 TFS(&tfs_yes_no
), RF4CE_NWK_USR_STR_SPECIFIED_MASK
,
1218 {&hf_rf4ce_nwk_app_capabilities_supported_dev_num
,
1219 {"Number of Supported Device Types", "rf4ce-nwk.app_capabilities.supported_dev_num",
1221 NULL
, RF4CE_NWK_SUPPORTED_DEV_NUM_MASK
,
1223 {&hf_rf4ce_nwk_app_capabilities_reserved1
,
1224 {"Reserved", "rf4ce-nwk.app_capabilities.reserved1",
1226 NULL
, RF4CE_NWK_RESERVED1_MASK
,
1228 {&hf_rf4ce_nwk_app_capabilities_supported_profiles_num
,
1229 {"Number of Supported Profiles", "rf4ce-nwk.app_capabilities.supported_profiles_num",
1231 NULL
, RF4CE_NWK_SUPPORTED_PROFILES_NUM_MASK
,
1233 {&hf_rf4ce_nwk_app_capabilities_reserved2
,
1234 {"Reserved", "rf4ce-nwk.app_capabilities.reserved2",
1236 NULL
, RF4CE_NWK_RESERVED2_MASK
,
1238 {&hf_rf4ce_nwk_usr_str
,
1239 {"User String", "rf4ce-nwk.usr_str",
1240 FT_BYTES
, BASE_NONE
,
1243 {&hf_rf4ce_nwk_usr_str_disc_rsp_app_usr_str
,
1244 {"App Specific User String", "rf4ce-nwk.usr_str.disc_rsp.app_usr_str",
1245 FT_STRING
, BASE_NONE
,
1248 {&hf_rf4ce_nwk_usr_str_disc_rsp_null
,
1249 {"NULL-terminator", "rf4ce-nwk.usr_str.disc_rsp.null",
1253 {&hf_rf4ce_nwk_usr_str_disc_rsp_reserved
,
1254 {"Reserved", "rf4ce-nwk.usr_str.disc_rsp.reserved",
1255 FT_UINT16
, BASE_HEX
,
1258 {&hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_tertiary
,
1259 {"Tertiary Class Descriptor", "rf4ce-nwk.usr_str.disc_rsp.class_descriptor.tertiary",
1263 {&hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_secondary
,
1264 {"Secondary Class Descriptor", "rf4ce-nwk.usr_str.disc_rsp.class_descriptor.secondary",
1268 {&hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_primary
,
1269 {"Primary Class Descriptor", "rf4ce-nwk.usr_str.disc_rsp.class_descriptor.primary",
1273 {&hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_class_num
,
1274 {"Class Number", "rf4ce-nwk.usr_str.disc_rsp.class_descriptor.class_number",
1276 VALS(rf4ce_nwk_usr_str_disc_rsp_class_desc_class_num_vals
), RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_MASK
,
1278 {&hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_duplicate_class_num_handling
,
1279 {"Duplicate Class Number Handling", "rf4ce-nwk.usr_str.disc_rsp.class_descriptor.duplicate_class_num_handling",
1281 VALS(rf4ce_nwk_usr_str_disc_rsp_class_desc_duplicate_class_num_handling_vals
), RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_DUPLICATE_CLASS_NUM_HANDLING_MASK
,
1283 {&hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_reserved
,
1284 {"Reserved", "rf4ce-nwk.usr_str.disc_rsp.class_descriptor.reserved",
1286 NULL
, RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_RESERVED_MASK
,
1288 {&hf_rf4ce_nwk_usr_str_disc_rsp_discovery_lqi_threshold
,
1289 {"Discovery LQI Threshold", "rf4ce-nwk.usr_str.disc_rsp.discovery_lqi_threshold",
1293 {&hf_rf4ce_nwk_app_cap_dev_type
,
1294 {"Device Type", "rf4ce-nwk.app_cap.dev_type",
1298 {&hf_rf4ce_nwk_app_cap_profile_id
,
1299 {"Profile ID", "rf4ce-nwk.app_cap.profile_id",
1303 {&hf_rf4ce_nwk_requested_dev_type
,
1304 {"Requested Device Type", "rf4ce-nwk.requested_dev_type",
1306 VALS(rf4ce_nwk_device_type_vals
), 0x0,
1308 {&hf_rf4ce_nwk_disc_resp_status
,
1309 {"Status", "rf4ce-nwk.disc_resp.status",
1311 VALS(rf4ce_nwk_disc_status_vals
), 0x0,
1313 {&hf_rf4ce_nwk_disc_resp_lqi
,
1314 {"Discovery Request LQI", "rf4ce-nwk.disc_resp.lqi",
1318 {&hf_rf4ce_nwk_pair_req_nwk_addr
,
1319 {"Network Address", "rf4ce-nwk.pair_req.nwk_addr",
1320 FT_UINT16
, BASE_HEX
,
1323 {&hf_rf4ce_nwk_pair_req_key_exch_num
,
1324 {"Key Exchange Transfer Count", "rf4ce-nwk.pair_req.key_exch_num",
1328 {&hf_rf4ce_nwk_pair_rsp_status
,
1329 {"Status", "rf4ce-nwk.pair_rsp.status",
1331 VALS(rf4ce_nwk_disc_status_vals
), 0x0,
1333 {&hf_rf4ce_nwk_pair_rsp_allocated_nwk_addr
,
1334 {"Allocated Network Address", "rf4ce-nwk.pair_rsp.allocated_nwk_addr",
1335 FT_UINT16
, BASE_HEX
,
1338 {&hf_rf4ce_nwk_pair_rsp_nwk_addr
,
1339 {"Network Address", "rf4ce-nwk.pair_rsp.nwk_addr",
1340 FT_UINT16
, BASE_HEX
,
1343 {&hf_rf4ce_nwk_seed_seq_num
,
1344 {"Seed Sequence Number", "rf4ce-nwk.key_seed.seed_seq_num",
1348 {&hf_rf4ce_nwk_seed_data
,
1349 {"Seed Data", "rf4ce-nwk.key_seed.seed_data",
1350 FT_BYTES
, SEP_COLON
,
1353 {&hf_rf4ce_nwk_ping_options
,
1354 {"Ping Options", "rf4ce-nwk.ping_options",
1358 {&hf_rf4ce_nwk_ping_payload
,
1359 {"Ping Payload", "rf4ce-nwk.ping_payload",
1360 FT_UINT32
, BASE_HEX
,
1365 {"Ping Payload", "rf4ce-nwk.mic",
1366 FT_UINT32
, BASE_HEX
,
1370 {&hf_rf4ce_nwk_unparsed_payload
,
1371 {"Unparsed Payload", "rf4ce-nwk.unparsed_payload",
1372 FT_BYTES
, SEP_COLON
,
1377 /* Setup protocol subtree array */
1378 static int *ett
[] = {
1380 &ett_rf4ce_nwk_payload
,
1381 &ett_rf4ce_nwk_vendor_info
,
1382 &ett_rf4ce_nwk_usr_str
,
1383 &ett_rf4ce_nwk_usr_str_class_descriptor
,
1384 &ett_rf4ce_nwk_dev_types_list
,
1385 &ett_rf4ce_nwk_profiles_list
,
1388 proto_rf4ce_nwk
= proto_register_protocol("RF4CE Network Layer", "RF4CE", RF4CE_PROTOABBREV_NWK
);
1389 proto_register_field_array(proto_rf4ce_nwk
, hf
, array_length(hf
));
1390 proto_register_subtree_array(ett
, array_length(ett
));
1392 register_cleanup_routine(rf4ce_cleanup
);
1394 register_dissector(RF4CE_PROTOABBREV_NWK
, dissect_rf4ce_nwk_common
, proto_rf4ce_nwk
);
1396 static uat_field_t key_uat_fields
[] =
1398 UAT_FLD_CSTRING(uat_security_records
, sec_str
, "Byte sequence",
1399 "In case of NWK key type it is a 16-byte key in hexadecimal with optional dash-,\n"
1400 "colon-, or space-separator characters, or \n"
1401 "a 16-character string in double-quotes.\n"
1402 "In case of Vendor Secret type it is a secret byte sequence\n"
1403 "to calculate NWK keys during Key Exchange procedure."),
1404 UAT_FLD_VS(uat_security_records
, type
, "Type", sec_str_type_vals
, "Type of a security string."),
1405 UAT_FLD_CSTRING(uat_security_records
, label
, "Label", "User label for a security string."),
1408 rf4ce_security_table_uat
=
1409 uat_new("Pre-configured security table",
1410 sizeof(uat_security_record_t
),
1413 &uat_security_records
,
1414 &num_uat_security_records
,
1415 UAT_AFFECTS_DISSECTION
, /* affects dissection of packets, but not set of named fields */
1416 NULL
, /* TODO: ptr to help manual? */
1417 uat_sec_record_copy_cb
,
1418 uat_sec_record_update_cb
,
1419 uat_sec_record_free_cb
,
1420 uat_sec_record_post_update
,
1424 module_t
*rf4ce_prefs
= prefs_register_protocol(proto_rf4ce_nwk
, NULL
);
1426 prefs_register_uat_preference(
1429 "Pre-configured security strings",
1430 "Pre-configured vendor secrets or network keys.",
1431 rf4ce_security_table_uat
);
1434 void proto_reg_handoff_rf4ce_nwk(void)
1436 rf4ce_gdp_handle
= find_dissector_add_dependency(RF4CE_PROTOABBREV_PROFILE
, proto_rf4ce_nwk
);
1438 /* create_dissector_handle(dissect_rf4ce_nwk_common, proto_rf4ce_nwk); */
1439 dissector_add_for_decode_as(IEEE802154_PROTOABBREV_WPAN_PANID
, find_dissector(RF4CE_PROTOABBREV_NWK
));
1440 heur_dissector_add(IEEE802154_PROTOABBREV_WPAN
, dissect_rf4ce_nwk_heur
, "Radio Frequency for Consumer Electronics over IEEE 802.15.4", RF4CE_PROTOABBREV_NWK
, proto_rf4ce_nwk
, HEURISTIC_ENABLE
);