1 /* packet-ieee802154.c
2 *
3 * Multipurpose frame support
4 * By Devan Lai <devanl@davisinstruments.com>
5 * Copyright 2019 Davis Instruments
6 *
7 * IEEE 802.15.4-2015 CCM* nonce for TSCH mode
8 * By Maxime Brunelle <Maxime.Brunelle@trilliant.com>
9 * Copyright 2019 Trilliant Inc.
10 *
11 * IEEE802154 TAP link type
12 * By James Ko <jck@exegin.com>
13 * Copyright 2019 Exegin Technologies Limited
14 *
15 * 4-byte FCS support and ACK tracking
16 * By Carl Levesque Imbeault <carl.levesque@trilliant.com>
17 * Copyright 2018 Trilliant Inc.
18 * Integrated and added FCS type enum
19 * by James Ko <jck@exegin.com>
20 * Copyright 2019 Exegin Technologies Limited
21 *
22 * Auxiliary Security Header support and
23 * option to force TI CC24xx FCS format
24 * By Jean-Francois Wauthy <jfw@info.fundp.ac.be>
25 * Copyright 2009 The University of Namur, Belgium
26 *
27 * IEEE 802.15.4 Dissectors for Wireshark
28 * By Owen Kirby <osk@exegin.com>
29 * Copyright 2007 Exegin Technologies Limited
30 *
31 * Wireshark - Network traffic analyzer
32 * By Gerald Combs <gerald@wireshark.org>
33 * Copyright 1998 Gerald Combs
34 *
35 * SPDX-License-Identifier: GPL-2.0-or-later
36 *------------------------------------------------------------
37 *
38 * In IEEE 802.15.4 packets, all fields are little endian. And
39 * Each byte is transmitted least significant bit first (reflected
40 * bit ordering).
41 *------------------------------------------------------------
42 *
43 * Most IEEE 802.15.4 Packets have the following format:
44 * | FCF |Seq No| Addressing | Data | FCS |
45 * |2 bytes|1 byte|0 to 20 bytes|Length-(Overhead) bytes|2/4 Bytes|
46 *------------------------------------------------------------
47 *
48 * Multipurpose frame packets have the following format:
49 * | FCF | Seq No | Addressing | Data | FCS |
50 * |1/2 bytes|0/1 bytes|0 to 20 bytes|Length-(Overhead) bytes|2 bytes|
51 *------------------------------------------------------------
52 *
53 * CRC16 is calculated using the x^16 + x^12 + x^5 + 1 polynomial
54 * as specified by ITU-T, and is calculated over the IEEE 802.15.4
55 * packet (excluding the FCS) as transmitted over the air. Note,
56 * that because the least significan bits are transmitted first, this
57 * will require reversing the bit-order in each byte. Also, unlike
58 * most CRC algorithms, IEEE 802.15.4 uses an initial and final value
59 * of 0x0000, instead of 0xffff (which is used by the ITU-T).
60 *
61 * For a 4-byte FCS, CRC32 is calculated using the ITU-T CRC32.
62 *
63 * (Fun fact: the reference to "a 32-bit CRC equivalent to ANSI X3.66-1979"
64 * in IEEE Std 802.15.4-2015 nonwithstanding, ANSI X3.66-1979 does not
65 * describe any 32-bit CRC, only a 16-bit CRC from ITU-T V.41. ITU-T
66 * V.42 describes both a 16-bit and 32-bit CRC; all the 16-bit CRCs
67 * floating around seem to use the same generator polynomial,
68 * x^16 + x^12 + x^5 + 1, but have different initial conditions and
69 * no-error final remainder; the 32-bit CRC from V.42 and the one
70 * described in IEEE Std 802.15.4-2015 also use the same generator
71 * polynomial.)
72 *------------------------------------------------------------
73 *
74 * This dissector supports both link-layer IEEE 802.15.4 captures
75 * and IEEE 802.15.4 packets encapsulated within other layers.
76 * Additionally, support has been provided for 16-bit and 32-bit
77 * FCS, as well as for frames with no FCS but with a 16-bit
78 * ChipCon/Texas Instruments CC24xx-style metadata field.
79 *------------------------------------------------------------
80 */
81
82 /* Include files */
83 #include "config.h"
84 #include <epan/packet.h>
85 #include <epan/decode_as.h>
86 #include <epan/exceptions.h>
87 #include <epan/crc16-tvb.h>
88 #include <epan/crc32-tvb.h>
89 #include <epan/expert.h>
90 #include <epan/addr_resolv.h>
91 #include <epan/address_types.h>
92 #include <epan/conversation.h>
93 #include <epan/conversation_table.h>
94 #include <epan/conversation_filter.h>
95 #include <epan/prefs.h>
96 #include <epan/uat.h>
97 #include <epan/strutil.h>
98 #include <epan/to_str.h>
99 #include <epan/show_exception.h>
100 #include <epan/proto_data.h>
101 #include <epan/etypes.h>
102 #include <epan/oui.h>
103 #include <epan/tap.h>
104 #include <wsutil/pint.h>
105
106 /* Use libgcrypt for cipher libraries. */
107 #include <wsutil/wsgcrypt.h>
108
109 #include "packet-ieee802154.h"
110 #include "packet-sll.h"
111
112 void proto_register_ieee802154(void);
113 void proto_reg_handoff_ieee802154(void);
114
115 /* Dissection Options for dissect_ieee802154_common */
116 #define DISSECT_IEEE802154_OPTION_CC24xx 0x00000001 /* Frame has TI CC24xx metadata, not an FCS, at the end */
117 #define DISSECT_IEEE802154_OPTION_ZBOSS 0x00000002 /* ZBOSS traffic dump */
118
119 /* ethertype for 802.15.4 tag - encapsulating an Ethernet packet */
120 static unsigned int ieee802154_ethertype = 0x809A;
121
122 /* FCS Types used by user configuration */
123 #define IEEE802154_CC24XX_METADATA 0 /* Not an FCS, but TI CC24xx metadata */
124 #define IEEE802154_FCS_16_BIT 1 /* ITU-T CRC16 */
125 #define IEEE802154_FCS_32_BIT 2 /* ITU-T CRC32 */
126
127 static gint ieee802154_fcs_type = IEEE802154_FCS_16_BIT;
128
129 /* 802.15.4 TAP Fields */
130 typedef enum {
131 IEEE802154_TAP_FCS_TYPE = 0x0000,
132 IEEE802154_TAP_RSS = 0x0001,
133 IEEE802154_TAP_BIT_RATE = 0x0002,
134 IEEE802154_TAP_CHANNEL_ASSIGNMENT = 0x0003,
135 IEEE802154_TAP_SUN_PHY_INFO = 0x0004,
136 IEEE802154_TAP_START_OF_FRAME_TS = 0x0005,
137 IEEE802154_TAP_END_OF_FRAME_TS = 0x0006,
138 IEEE802154_TAP_ASN = 0x0007,
139 IEEE802154_TAP_SLOT_START_TS = 0x0008,
140 IEEE802154_TAP_TIMESLOT_LENGTH = 0x0009,
141 IEEE802154_TAP_LQI = 0x000A,
142 IEEE802154_TAP_CHANNEL_FREQUENCY = 0x000B,
143 IEEE802154_TAP_CHANNEL_PLAN = 0x000C,
144 } ieee802154_info_type_t;
145
146 typedef enum {
147 IEEE802154_FCS_TYPE_NONE = 0,
148 IEEE802154_FCS_TYPE_16_BIT = 1, /* ITU-T CRC16 */
149 IEEE802154_FCS_TYPE_32_BIT = 2, /* ITU-T CRC32 */
150 } ieee802154_fcs_type_t;
151
152 typedef enum {
153 IEEE802154_SUN_TYPE_FSK_A = 0x00,
154 IEEE802154_SUN_TYPE_FSK_B = 0x01,
155 IEEE802154_SUN_TYPE_OQPSK_A = 0x02,
156 IEEE802154_SUN_TYPE_OQPSK_B = 0x03,
157 IEEE802154_SUN_TYPE_OQPSK_C = 0x04,
158 IEEE802154_SUN_TYPE_OFDM_OPT1 = 0x05,
159 IEEE802154_SUN_TYPE_OFDM_OPT2 = 0x06,
160 IEEE802154_SUN_TYPE_OFDM_OPT3 = 0x07,
161 IEEE802154_SUN_TYPE_OFDM_OPT4 = 0x08,
162 } ieee802154_sun_type_t;
163
164 /* boolean value set if the FCS must be ok before payload is dissected */
165 static gboolean ieee802154_fcs_ok = TRUE;
166
167 /* boolean value set to enable ack tracking */
168 static gboolean ieee802154_ack_tracking = FALSE;
169
170 /* boolean value set to enable 802.15.4e dissection compatibility */
171 static gboolean ieee802154e_compatibility = FALSE;
172
173 /* TSCH ASN for nonce in decryption */
174 static guint64 ieee802154_tsch_asn = 0;
175
176 static const char *ieee802154_user = "User";
177
178 static wmem_tree_t* mac_key_hash_handlers;
179
180 #ifndef ROUND_UP
181 #define ROUND_UP(_offset_, _align_) (((_offset_) + (_align_) - 1) / (_align_) * (_align_))
182 #endif
183
184 /*
185 * Address Hash Tables
186 *
187 */
188 ieee802154_map_tab_t ieee802154_map = { NULL, NULL };
189
190 /*
191 * Static Address Mapping UAT
192 *
193 */
194 /* UAT entry structure. */
195 typedef struct {
196 guchar *eui64;
197 guint eui64_len;
198 guint addr16;
199 guint pan;
200 } static_addr_t;
201
202 /* UAT variables */
203 static uat_t *static_addr_uat = NULL;
204 static static_addr_t *static_addrs = NULL;
205 static guint num_static_addrs = 0;
206
207 static void*
addr_uat_copy_cb(void * dest,const void * source,size_t len _U_)208 addr_uat_copy_cb(void *dest, const void *source, size_t len _U_)
209 {
210 const static_addr_t* o = (const static_addr_t*)source;
211 static_addr_t* d = (static_addr_t*)dest;
212
213 d->eui64 = (guchar *)g_memdup2(o->eui64, o->eui64_len);
214 d->eui64_len = o->eui64_len;
215 d->addr16 = o->addr16;
216 d->pan = o->pan;
217
218 return dest;
219 }
220
221 /* Sanity-checks a UAT record. */
222 static gboolean
addr_uat_update_cb(void * r,char ** err)223 addr_uat_update_cb(void *r, char **err)
224 {
225 static_addr_t *map = (static_addr_t *)r;
226 /* Ensure a valid short address */
227 if (map->addr16 >= IEEE802154_NO_ADDR16) {
228 *err = g_strdup("Invalid short address");
229 return FALSE;
230 }
231 /* Ensure a valid PAN identifier. */
232 if (map->pan >= IEEE802154_BCAST_PAN) {
233 *err = g_strdup("Invalid PAN identifier");
234 return FALSE;
235 }
236 /* Ensure a valid EUI-64 length */
237 if (map->eui64_len != sizeof(guint64)) {
238 *err = g_strdup("Invalid EUI-64 length");
239 return FALSE;
240 }
241 return TRUE;
242 } /* ieee802154_addr_uat_update_cb */
243
244 static void
addr_uat_free_cb(void * r)245 addr_uat_free_cb(void *r)
246 {
247 static_addr_t *rec = (static_addr_t *)r;
248 g_free(rec->eui64);
249 }
250
251 /* Field callbacks. */
252 UAT_HEX_CB_DEF(addr_uat, addr16, static_addr_t)
253 UAT_HEX_CB_DEF(addr_uat, pan, static_addr_t)
254 UAT_BUFFER_CB_DEF(addr_uat, eui64, static_addr_t, eui64, eui64_len)
255
256 /*
257 * Decryption Keys UAT
258 */
259
260 /* UAT variables */
261 static uat_t *ieee802154_key_uat = NULL;
262 static ieee802154_key_t *ieee802154_keys = NULL;
263 static guint num_ieee802154_keys = 0;
264
ieee802154_key_post_update_cb(void)265 static void ieee802154_key_post_update_cb(void)
266 {
267 guint i;
268 GByteArray *bytes;
269
270 for (i = 0; i < num_ieee802154_keys; i++)
271 {
272 switch (ieee802154_keys[i].hash_type) {
273 case KEY_HASH_NONE:
274 case KEY_HASH_ZIP:
275 /* Get the IEEE 802.15.4 decryption key. */
276 bytes = g_byte_array_new();
277 if (hex_str_to_bytes(ieee802154_keys[i].pref_key, bytes, FALSE))
278 {
279 if (ieee802154_keys[i].hash_type == KEY_HASH_ZIP) {
280 char digest[32];
281
282 if (!ws_hmac_buffer(GCRY_MD_SHA256, digest, "ZigBeeIP", 8, bytes->data, IEEE802154_CIPHER_SIZE)) {
283 /* Copy upper hashed bytes to the key */
284 memcpy(ieee802154_keys[i].key, &digest[IEEE802154_CIPHER_SIZE], IEEE802154_CIPHER_SIZE);
285 /* Copy lower hashed bytes to the MLE key */
286 memcpy(ieee802154_keys[i].mle_key, digest, IEEE802154_CIPHER_SIZE);
287 } else {
288 /* Just copy the keys verbatim */
289 memcpy(ieee802154_keys[i].key, bytes->data, IEEE802154_CIPHER_SIZE);
290 memcpy(ieee802154_keys[i].mle_key, bytes->data, IEEE802154_CIPHER_SIZE);
291 }
292 } else {
293 /* Just copy the keys verbatim */
294 memcpy(ieee802154_keys[i].key, bytes->data, IEEE802154_CIPHER_SIZE);
295 memcpy(ieee802154_keys[i].mle_key, bytes->data, IEEE802154_CIPHER_SIZE);
296 }
297 }
298 g_byte_array_free(bytes, TRUE);
299 break;
300 case KEY_HASH_THREAD:
301 /* XXX - TODO? */
302 break;
303 }
304 }
305 }
306
ieee802154_key_update_cb(void * r,char ** err)307 static gboolean ieee802154_key_update_cb(void *r, char **err)
308 {
309 ieee802154_key_t* rec = (ieee802154_key_t*)r;
310 GByteArray *bytes;
311
312 switch (rec->hash_type) {
313 case KEY_HASH_NONE:
314 case KEY_HASH_ZIP:
315 bytes = g_byte_array_new();
316 if (hex_str_to_bytes(rec->pref_key, bytes, FALSE) == FALSE)
317 {
318 *err = g_strdup("Invalid key");
319 g_byte_array_free(bytes, TRUE);
320 return FALSE;
321 }
322
323 if (bytes->len < IEEE802154_CIPHER_SIZE)
324 {
325 *err = g_strdup_printf("Key must be at least %d bytes", IEEE802154_CIPHER_SIZE);
326 g_byte_array_free(bytes, TRUE);
327 return FALSE;
328 }
329 g_byte_array_free(bytes, TRUE);
330 break;
331 case KEY_HASH_THREAD:
332 /* XXX - TODO? */
333 break;
334 }
335
336 return TRUE;
337 }
338
ieee802154_key_copy_cb(void * n,const void * o,size_t siz _U_)339 static void* ieee802154_key_copy_cb(void* n, const void* o, size_t siz _U_) {
340 ieee802154_key_t* new_record = (ieee802154_key_t*)n;
341 const ieee802154_key_t* old_record = (const ieee802154_key_t*)o;
342
343 new_record->pref_key = g_strdup(old_record->pref_key);
344 new_record->key_index = old_record->key_index;
345 new_record->hash_type = old_record->hash_type;
346
347 return new_record;
348 }
349
ieee802154_key_free_cb(void * r)350 static void ieee802154_key_free_cb(void*r) {
351 ieee802154_key_t* rec = (ieee802154_key_t *)r;
352
353 g_free(rec->pref_key);
354 }
355
356 /* Field callbacks. */
357 UAT_CSTRING_CB_DEF(key_uat, pref_key, ieee802154_key_t)
358 UAT_DEC_CB_DEF(key_uat, key_index, ieee802154_key_t)
359 UAT_VS_DEF(key_uat, hash_type, ieee802154_key_t, ieee802154_key_hash, KEY_HASH_NONE, "No hash")
360
361
362 /*-------------------------------------
363 * Dissector Function Prototypes
364 *-------------------------------------
365 */
366
367 /* Dissection Routines. */
368 static int dissect_ieee802154_nonask_phy (tvbuff_t *, packet_info *, proto_tree *, void *);
369 static int dissect_ieee802154 (tvbuff_t *, packet_info *, proto_tree *, void *);
370 static int dissect_ieee802154_nofcs (tvbuff_t *, packet_info *, proto_tree *, void *);
371 static int dissect_ieee802154_cc24xx (tvbuff_t *, packet_info *, proto_tree *, void *);
372 static int dissect_ieee802154_tap (tvbuff_t *, packet_info *, proto_tree *, void *);
373 static tvbuff_t *dissect_zboss_specific (tvbuff_t *, packet_info *, proto_tree *);
374 static void dissect_ieee802154_common (tvbuff_t *, packet_info *, proto_tree *, guint, guint);
375 static void ieee802154_dissect_fcs(tvbuff_t *tvb, proto_tree *ieee802154_tree, guint fcs_len, gboolean fcs_ok);
376 static void ieee802154_dissect_cc24xx_metadata(tvbuff_t *tvb, proto_tree *ieee802154_tree, gboolean fcs_ok);
377 static ieee802154_fcs_type_t dissect_ieee802154_tap_tlvs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
378
379 /* Information Elements */
380 static int dissect_ieee802154_header_ie (tvbuff_t *, packet_info *, proto_tree *, guint, ieee802154_packet *);
381 static int dissect_ieee802154_payload_ie (tvbuff_t *, packet_info *, proto_tree *, guint, ieee802154_packet *);
382 static int dissect_802154_eb_filter (tvbuff_t *, packet_info *, proto_tree *, void *);
383 static int dissect_802154_tsch_time_sync (tvbuff_t *, packet_info *, proto_tree *, void *);
384 static int dissect_802154_tsch_timeslot (tvbuff_t *, packet_info *, proto_tree *, void *);
385 static int dissect_802154_tsch_slotframe_link (tvbuff_t *, packet_info *, proto_tree *, void *);
386 static int dissect_802154_channel_hopping (tvbuff_t *, packet_info *, proto_tree *, void *);
387 /* Sub-dissector helpers. */
388 static void dissect_ieee802154_fcf (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *, guint *);
389 static void dissect_ieee802154_command (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
390 static void dissect_ieee802154_assoc_req (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
391 static void dissect_ieee802154_assoc_rsp (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
392 static void dissect_ieee802154_disassoc (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
393 static void dissect_ieee802154_realign (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
394 static void dissect_ieee802154_gtsreq (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
395
396 /* Decryption helpers. */
397 static tvbuff_t *dissect_ieee802154_decrypt(tvbuff_t *, guint, packet_info *, ieee802154_packet *, ieee802154_decrypt_info_t*);
398
399 static guint ieee802154_set_mac_key(ieee802154_packet *packet, unsigned char *key, unsigned char *alt_key, ieee802154_key_t *uat_key);
400 static void tsch_ccm_init_nonce(guint64 addr, guint64 asn, gchar* generic_nonce);
401
402 /* Initialize Protocol and Registered fields */
403 static int proto_ieee802154_nonask_phy = -1;
404 static int hf_ieee802154_nonask_phy_preamble = -1;
405 static int hf_ieee802154_nonask_phy_sfd = -1;
406 static int hf_ieee802154_nonask_phy_length = -1;
407 static int hf_ieee802154_nonask_phr = -1;
408
409 static int proto_ieee802154 = -1;
410 static int proto_ieee802154_tap = -1;
411 static int hf_ieee802154_frame_length = -1;
412 static int hf_ieee802154_fcf = -1;
413 static int hf_ieee802154_frame_type = -1;
414 static int hf_ieee802154_security = -1;
415 static int hf_ieee802154_pending = -1;
416 static int hf_ieee802154_ack_request = -1;
417 static int hf_ieee802154_pan_id_compression = -1;
418 static int hf_ieee802154_fcf_reserved = -1;
419 static int hf_ieee802154_seqno_suppression = -1;
420 static int hf_ieee802154_ie_present = -1;
421 static int hf_ieee802154_src_addr_mode = -1;
422 static int hf_ieee802154_version = -1;
423 static int hf_ieee802154_dst_addr_mode = -1;
424
425 static int hf_ieee802154_mpf_long_frame_control = -1;
426 static int hf_ieee802154_mpf_dst_addr_mode = -1;
427 static int hf_ieee802154_mpf_src_addr_mode = -1;
428 static int hf_ieee802154_mpf_pan_id_present = -1;
429 static int hf_ieee802154_mpf_security = -1;
430 static int hf_ieee802154_mpf_seqno_suppression = -1;
431 static int hf_ieee802154_mpf_pending = -1;
432 static int hf_ieee802154_mpf_version = -1;
433 static int hf_ieee802154_mpf_ack_request = -1;
434 static int hf_ieee802154_mpf_ie_present = -1;
435
436 static int hf_ieee802154_header_ies = -1;
437 static int hf_ieee802154_header_ie_tlv = -1;
438 static int hf_ieee802154_header_ie_type = -1;
439 static int hf_ieee802154_header_ie_id = -1;
440 static int hf_ieee802154_header_ie_length = -1;
441 static int hf_ieee802154_ie_unknown_content = -1;
442 static int hf_ieee802154_hie_unsupported = -1;
443 static int hf_ieee802154_hie_time_correction = -1;
444 static int hf_ieee802154_hie_ht1 = -1;
445 static int hf_ieee802154_hie_ht2 = -1;
446 static int hf_ieee802154_nack = -1;
447 static int hf_ieee802154_hie_time_correction_time_sync_info = -1;
448 static int hf_ieee802154_hie_time_correction_value = -1;
449 static int hf_ieee802154_hie_csl = -1;
450 static int hf_ieee802154_hie_csl_phase = -1;
451 static int hf_ieee802154_hie_csl_period = -1;
452 static int hf_ieee802154_hie_csl_rendezvous_time = -1;
453 static int hf_ieee802154_hie_global_time = -1;
454 static int hf_ieee802154_hie_global_time_value = -1;
455 static int hf_ieee802154_hie_vendor_specific = -1;
456 static int hf_ieee802154_hie_vendor_specific_vendor_oui = -1;
457 static int hf_ieee802154_hie_vendor_specific_content = -1;
458 static int hf_ieee802154_payload_ies = -1;
459 static int hf_ieee802154_payload_ie_tlv = -1;
460 static int hf_ieee802154_payload_ie_type = -1;
461 static int hf_ieee802154_payload_ie_id = -1;
462 static int hf_ieee802154_payload_ie_length = -1;
463 static int hf_ieee802154_pie_unsupported = -1;
464 static int hf_ieee802154_pie_termination = -1;
465 static int hf_ieee802154_pie_vendor = -1;
466 static int hf_ieee802154_pie_vendor_oui = -1;
467 static int hf_ieee802154_pie_ietf = -1;
468 static int hf_ieee802154_mlme = -1;
469 static int hf_ieee802154_mlme_ie_data = -1;
470 static int hf_ieee802154_mlme_ie_unsupported = -1;
471 static int hf_ieee802154_psie = -1;
472 static int hf_ieee802154_psie_type = -1;
473 static int hf_ieee802154_psie_id_short = -1;
474 static int hf_ieee802154_psie_length_short = -1;
475 static int hf_ieee802154_psie_id_long = -1;
476 static int hf_ieee802154_psie_length_long = -1;
477
478 static int hf_ieee802154_tsch_sync = -1;
479 static int hf_ieee802154_tsch_asn = -1;
480 static int hf_ieee802154_tsch_join_metric = -1;
481 static int hf_ieee802154_tsch_slotframe = -1;
482 static int hf_ieee802154_tsch_link_info = -1;
483 static int hf_ieee802154_tsch_slotf_link_nb_slotf = -1;
484 static int hf_ieee802154_tsch_slotf_link_slotf_handle= -1;
485 static int hf_ieee802154_tsch_slotf_size = -1;
486 static int hf_ieee802154_tsch_slotf_link_nb_links = -1;
487 static int hf_ieee802154_tsch_slotf_link_timeslot = -1;
488 static int hf_ieee802154_tsch_slotf_link_channel_offset = -1;
489 static int hf_ieee802154_tsch_slotf_link_options = -1;
490 static int hf_ieee802154_tsch_slotf_link_options_tx = -1;
491 static int hf_ieee802154_tsch_slotf_link_options_rx = -1;
492 static int hf_ieee802154_tsch_slotf_link_options_shared = -1;
493 static int hf_ieee802154_tsch_slotf_link_options_timkeeping = -1;
494 static int hf_ieee802154_tsch_slotf_link_options_priority = -1;
495 static int hf_ieee802154_tsch_channel_hopping = -1;
496 static int hf_ieee802154_tsch_hopping_sequence_id = -1;
497 static int hf_ieee802154_tsch_timeslot = -1;
498 static int hf_ieee802154_tsch_timeslot_id = -1;
499 static int hf_ieee802154_tsch_timeslot_cca_offset = -1;
500 static int hf_ieee802154_tsch_timeslot_cca = -1;
501 static int hf_ieee802154_tsch_timeslot_tx_offset = -1;
502 static int hf_ieee802154_tsch_timeslot_rx_offset = -1;
503 static int hf_ieee802154_tsch_timeslot_rx_ack_delay = -1;
504 static int hf_ieee802154_tsch_timeslot_tx_ack_delay = -1;
505 static int hf_ieee802154_tsch_timeslot_rx_wait = -1;
506 static int hf_ieee802154_tsch_timeslot_ack_wait = -1;
507 static int hf_ieee802154_tsch_timeslot_turnaround = -1;
508 static int hf_ieee802154_tsch_timeslot_max_ack = -1;
509 static int hf_ieee802154_tsch_timeslot_max_tx = -1;
510 static int hf_ieee802154_tsch_timeslot_length = -1;
511
512 static int hf_ieee802154_psie_eb_filter = -1;
513 static int hf_ieee802154_psie_eb_filter_pjoin = -1;
514 static int hf_ieee802154_psie_eb_filter_lqi = -1;
515 static int hf_ieee802154_psie_eb_filter_lqi_min = -1;
516 static int hf_ieee802154_psie_eb_filter_percent = -1;
517 static int hf_ieee802154_psie_eb_filter_percent_prob = -1;
518 static int hf_ieee802154_psie_eb_filter_attr_id = -1;
519 static int hf_ieee802154_psie_eb_filter_attr_id_bitmap = -1;
520 static int hf_ieee802154_p_ie_ietf_sub_id = -1;
521
522 static int hf_ieee802154_6top = -1;
523 static int hf_ieee802154_6top_version = -1;
524 static int hf_ieee802154_6top_type = -1;
525 static int hf_ieee802154_6top_flags_reserved = -1;
526 static int hf_ieee802154_6top_code = -1;
527 static int hf_ieee802154_6top_sfid = -1;
528 static int hf_ieee802154_6top_seqnum = -1;
529 static int hf_ieee802154_6top_metadata = -1;
530 static int hf_ieee802154_6top_cell_options = -1;
531 static int hf_ieee802154_6top_cell_option_tx = -1;
532 static int hf_ieee802154_6top_cell_option_rx = -1;
533 static int hf_ieee802154_6top_cell_option_shared = -1;
534 static int hf_ieee802154_6top_cell_option_reserved = -1;
535 static int hf_ieee802154_6top_num_cells = -1;
536 static int hf_ieee802154_6top_cell_list = -1;
537 static int hf_ieee802154_6top_rel_cell_list = -1;
538 static int hf_ieee802154_6top_cand_cell_list = -1;
539 static int hf_ieee802154_6top_cell = -1;
540 static int hf_ieee802154_6top_reserved = -1;
541 static int hf_ieee802154_6top_offset = -1;
542 static int hf_ieee802154_6top_max_num_cells = -1;
543 static int hf_ieee802154_6top_slot_offset = -1;
544 static int hf_ieee802154_6top_channel_offset = -1;
545 static int hf_ieee802154_6top_total_num_cells = -1;
546 static int hf_ieee802154_6top_payload = -1;
547
548 static int hf_ieee802159_mpx = -1;
549 static int hf_ieee802159_mpx_transaction_control = -1;
550 static int hf_ieee802159_mpx_transfer_type = -1;
551 static int hf_ieee802159_mpx_transaction_id = -1;
552 static int hf_ieee802159_mpx_transaction_id_as_multiplex_id = -1;
553 static int hf_ieee802159_mpx_fragment_number = -1;
554 static int hf_ieee802159_mpx_total_frame_size = -1;
555 static int hf_ieee802159_mpx_multiplex_id = -1;
556 static int hf_ieee802159_mpx_kmp_id = -1;
557 static int hf_ieee802159_mpx_kmp_vendor_oui = -1;
558 static int hf_ieee802159_mpx_fragment = -1;
559 static int hf_ieee802159_mpx_wisun_subid = -1;
560
561 static int proto_zboss = -1;
562 static int hf_zboss_direction = -1;
563 static int hf_zboss_page = -1;
564 static int hf_zboss_channel = -1;
565 static int hf_zboss_trace_number = -1;
566
567 static int hf_ieee802154_seqno = -1;
568 static int hf_ieee802154_dst_panID = -1;
569 static int hf_ieee802154_dst16 = -1;
570 static int hf_ieee802154_dst64 = -1;
571 static int hf_ieee802154_src_panID = -1;
572 static int hf_ieee802154_src16 = -1;
573 static int hf_ieee802154_src64 = -1;
574 static int hf_ieee802154_src64_origin = -1;
575 static int hf_ieee802154_addr16 = -1;
576 static int hf_ieee802154_addr64 = -1;
577 static int hf_ieee802154_fcs = -1;
578 static int hf_ieee802154_fcs32 = -1;
579 static int hf_ieee802154_rssi = -1;
580 static int hf_ieee802154_fcs_ok = -1;
581 static int hf_ieee802154_correlation = -1;
582
583 /* Registered fields for Command Packets */
584 static int hf_ieee802154_cmd_id = -1;
585 static int hf_ieee802154_cinfo_alt_coord = -1;
586 static int hf_ieee802154_cinfo_device_type = -1;
587 static int hf_ieee802154_cinfo_power_src = -1;
588 static int hf_ieee802154_cinfo_idle_rx = -1;
589 static int hf_ieee802154_cinfo_sec_capable = -1;
590 static int hf_ieee802154_cinfo_alloc_addr = -1;
591 static int hf_ieee802154_assoc_addr = -1;
592 static int hf_ieee802154_assoc_status = -1;
593 static int hf_ieee802154_disassoc_reason = -1;
594 static int hf_ieee802154_realign_pan = -1;
595 static int hf_ieee802154_realign_caddr = -1;
596 static int hf_ieee802154_realign_channel = -1;
597 static int hf_ieee802154_realign_addr = -1;
598 static int hf_ieee802154_realign_channel_page = -1;
599 static int hf_ieee802154_gtsreq_len = -1;
600 static int hf_ieee802154_gtsreq_dir = -1;
601 static int hf_ieee802154_gtsreq_type = -1;
602 static int hf_ieee802154_cmd_vendor_oui = -1;
603
604 /* Registered fields for Beacon Packets */
605 static int hf_ieee802154_beacon_order = -1;
606 static int hf_ieee802154_superframe_order = -1;
607 static int hf_ieee802154_cap = -1;
608 static int hf_ieee802154_superframe_battery_ext = -1;
609 static int hf_ieee802154_superframe_coord = -1;
610 static int hf_ieee802154_assoc_permit = -1;
611 static int hf_ieee802154_gts_count = -1;
612 static int hf_ieee802154_gts_permit = -1;
613 static int hf_ieee802154_gts_direction = -1;
614 static int hf_ieee802154_gts_address = -1;
615 static int hf_ieee802154_pending16 = -1;
616 static int hf_ieee802154_pending64 = -1;
617
618 /* Registered fields for Auxiliary Security Header */
619 static int hf_ieee802154_aux_security_header = -1;
620 static int hf_ieee802154_aux_sec_security_control = -1;
621 static int hf_ieee802154_aux_sec_security_level = -1;
622 static int hf_ieee802154_aux_sec_key_id_mode = -1;
623 static int hf_ieee802154_aux_sec_frame_counter_suppression = -1;
624 static int hf_ieee802154_aux_sec_asn_in_nonce = -1;
625 static int hf_ieee802154_aux_sec_reserved = -1;
626 static int hf_ieee802154_aux_sec_frame_counter = -1;
627 static int hf_ieee802154_aux_sec_key_source = -1;
628 static int hf_ieee802154_aux_sec_key_source_bytes = -1;
629 static int hf_ieee802154_aux_sec_key_index = -1;
630 static int hf_ieee802154_mic = -1;
631 static int hf_ieee802154_key_number = -1;
632
633 /* 802.15.4-2003 security */
634 static int hf_ieee802154_sec_frame_counter = -1;
635 static int hf_ieee802154_sec_key_sequence_counter = -1;
636
637 /* 802.15.4 ack */
638 static int hf_ieee802154_no_ack = -1;
639 static int hf_ieee802154_no_ack_request = -1;
640 static int hf_ieee802154_ack_in = -1;
641 static int hf_ieee802154_ack_to = -1;
642 static int hf_ieee802154_ack_time = -1;
643
644 /* 802.15.4 TAP */
645 static int hf_ieee802154_tap_version = -1;
646 static int hf_ieee802154_tap_reserved = -1;
647 static int hf_ieee802154_tap_length = -1;
648 static int hf_ieee802154_tap_data_length = -1;
649 static int hf_ieee802154_tap_tlv_type = -1;
650 static int hf_ieee802154_tap_tlv_length = -1;
651 static int hf_ieee802154_tap_tlv_unknown = -1;
652 static int hf_ieee802154_tap_tlv_padding = -1;
653 static int hf_ieee802154_tap_fcs_type = -1;
654 static int hf_ieee802154_tap_rss = -1;
655 static int hf_ieee802154_ch_page = -1;
656 static int hf_ieee802154_ch_num = -1;
657 static int hf_ieee802154_bit_rate = -1;
658 static int hf_ieee802154_sun_band = -1;
659 static int hf_ieee802154_sun_type = -1;
660 static int hf_ieee802154_sun_mode = -1;
661 static int hf_ieee802154_mode_fsk_a = -1;
662 static int hf_ieee802154_mode_fsk_b = -1;
663 static int hf_ieee802154_mode_oqpsk_a = -1;
664 static int hf_ieee802154_mode_oqpsk_b = -1;
665 static int hf_ieee802154_mode_oqpsk_c = -1;
666 static int hf_ieee802154_mode_ofdm = -1;
667 static int hf_ieee802154_sof_ts = -1;
668 static int hf_ieee802154_eof_ts = -1;
669 static int hf_ieee802154_slot_start_ts = -1;
670 static int hf_ieee802154_tap_timeslot_length = -1;
671 static int hf_ieee802154_tap_lqi = -1;
672 static int hf_ieee802154_chplan_start = -1;
673 static int hf_ieee802154_chplan_spacing = -1;
674 static int hf_ieee802154_chplan_channels = -1;
675 static int hf_ieee802154_ch_freq = -1;
676 static int hf_ieee802154_frame_start_offset = -1;
677 static int hf_ieee802154_frame_duration = -1;
678 static int hf_ieee802154_frame_end_offset = -1;
679 static int hf_ieee802154_asn = -1;
680
681 typedef struct _ieee802154_transaction_t {
682 guint64 dst64;
683 guint64 src64;
684 gint32 dst_addr_mode;
685 gint32 src_addr_mode;
686 guint16 dst16;
687 guint16 src16;
688 guint32 rqst_frame;
689 guint32 ack_frame;
690 nstime_t rqst_time;
691 nstime_t ack_time;
692 gboolean dst_pan_present;
693 gboolean src_pan_present;
694 guint16 dst_pan;
695 guint16 src_pan;
696 } ieee802154_transaction_t;
697
698 static const nstime_t ieee802154_transaction_timeout = NSTIME_INIT_SECS_MSECS(1, 0); // ACKs usually arrive within milliseconds
699
700 static wmem_tree_t *transaction_unmatched_pdus;
701 static wmem_tree_t *transaction_matched_pdus;
702
703 static ieee802154_transaction_t *transaction_start(packet_info *pinfo, proto_tree *tree, const ieee802154_packet *packet, guint32 *key);
704 static ieee802154_transaction_t *transaction_end(packet_info *pinfo, proto_tree *tree, const ieee802154_packet *packet, guint32 *key);
705
706 /* Initialize Subtree Pointers */
707 static gint ett_ieee802154_nonask_phy = -1;
708 static gint ett_ieee802154_nonask_phy_phr = -1;
709 static gint ett_ieee802154_tap = -1;
710 static gint ett_ieee802154_tap_header = -1;
711 static gint ett_ieee802154_tap_tlv = -1;
712 static gint ett_ieee802154 = -1;
713 static gint ett_ieee802154_fcf = -1;
714 static gint ett_ieee802154_auxiliary_security = -1;
715 static gint ett_ieee802154_aux_sec_control = -1;
716 static gint ett_ieee802154_aux_sec_key_id = -1;
717 static gint ett_ieee802154_fcs = -1;
718 static gint ett_ieee802154_cmd = -1;
719 static gint ett_ieee802154_superframe = -1;
720 static gint ett_ieee802154_gts = -1;
721 static gint ett_ieee802154_gts_direction = -1;
722 static gint ett_ieee802154_gts_descriptors = -1;
723 static gint ett_ieee802154_pendaddr = -1;
724 static gint ett_ieee802154_header_ies = -1;
725 static gint ett_ieee802154_header_ie = -1;
726 static gint ett_ieee802154_header_ie_tlv = -1;
727 static gint ett_ieee802154_hie_unsupported = -1;
728 static gint ett_ieee802154_hie_time_correction = -1;
729 static gint ett_ieee802154_hie_ht = -1;
730 static gint ett_ieee802154_hie_csl = -1;
731 static gint ett_ieee802154_hie_global_time = -1;
732 static gint ett_ieee802154_hie_vendor_specific = -1;
733 static gint ett_ieee802154_payload_ie = -1;
734 static gint ett_ieee802154_payload_ie_tlv = -1;
735 static gint ett_ieee802154_pie_termination = -1;
736 static gint ett_ieee802154_pie_vendor = -1;
737 static gint ett_ieee802154_pie_ietf = -1;
738 static gint ett_ieee802154_pie_unsupported = -1;
739 static gint ett_ieee802154_mlme = -1;
740 static gint ett_ieee802154_mlme_payload = -1;
741 static gint ett_ieee802154_mlme_payload_data = -1;
742 static gint ett_ieee802154_mlme_unsupported = -1;
743 static gint ett_ieee802154_tsch_slotframe = -1;
744 static gint ett_ieee802154_tsch_slotframe_list = -1;
745 static gint ett_ieee802154_tsch_slotframe_link = -1;
746 static gint ett_ieee802154_tsch_slotframe_link_options = -1;
747 static gint ett_ieee802154_tsch_timeslot = -1;
748 static gint ett_ieee802154_tsch_synch = -1;
749 static gint ett_ieee802154_channel_hopping = -1;
750 static gint ett_ieee802154_psie = -1;
751 static gint ett_ieee802154_eb_filter = -1;
752 static gint ett_ieee802154_eb_filter_bitmap = -1;
753 static gint ett_ieee802154_zigbee = -1;
754 static gint ett_ieee802154_zboss = -1;
755 static gint ett_ieee802154_p_ie_6top = -1;
756 static gint ett_ieee802154_p_ie_6top_cell_options = -1;
757 static gint ett_ieee802154_p_ie_6top_cell_list = -1;
758 static gint ett_ieee802154_p_ie_6top_cand_cell_list = -1;
759 static gint ett_ieee802154_p_ie_6top_rel_cell_list = -1;
760 static gint ett_ieee802154_p_ie_6top_cell = -1;
761 static gint ett_ieee802159_mpx = -1;
762 static gint ett_ieee802159_mpx_transaction_control = -1;
763
764 static expert_field ei_ieee802154_fcs_bitmask_len = EI_INIT;
765 static expert_field ei_ieee802154_invalid_addressing = EI_INIT;
766 static expert_field ei_ieee802154_invalid_panid_compression = EI_INIT;
767 static expert_field ei_ieee802154_invalid_panid_compression2 = EI_INIT;
768 static expert_field ei_ieee802154_fcs = EI_INIT;
769 static expert_field ei_ieee802154_decrypt_error = EI_INIT;
770 static expert_field ei_ieee802154_dst = EI_INIT;
771 static expert_field ei_ieee802154_src = EI_INIT;
772 static expert_field ei_ieee802154_frame_ver = EI_INIT;
773 /* static expert_field ei_ieee802154_frame_type = EI_INIT; */
774 static expert_field ei_ieee802154_seqno_suppression = EI_INIT;
775 static expert_field ei_ieee802154_ack_not_found = EI_INIT;
776 static expert_field ei_ieee802154_ack_request_not_found = EI_INIT;
777 static expert_field ei_ieee802154_time_correction_error = EI_INIT;
778 static expert_field ei_ieee802154_6top_unsupported_type = EI_INIT;
779 static expert_field ei_ieee802154_6top_unsupported_return_code = EI_INIT;
780 static expert_field ei_ieee802154_6top_unsupported_command = EI_INIT;
781 static expert_field ei_ieee802154_ie_unsupported_id = EI_INIT;
782 static expert_field ei_ieee802154_ie_unknown_extra_content = EI_INIT;
783 static expert_field ei_ieee802159_mpx_invalid_transfer_type = EI_INIT;
784 static expert_field ei_ieee802159_mpx_unsupported_kmp = EI_INIT;
785 static expert_field ei_ieee802159_mpx_unknown_kmp = EI_INIT;
786 static expert_field ei_ieee802154_missing_payload_ie = EI_INIT;
787 static expert_field ei_ieee802154_payload_ie_in_header = EI_INIT;
788 static expert_field ei_ieee802154_unsupported_cmd = EI_INIT;
789 static expert_field ei_ieee802154_unknown_cmd = EI_INIT;
790 static expert_field ei_ieee802154_tap_tlv_invalid_type = EI_INIT;
791 static expert_field ei_ieee802154_tap_tlv_invalid_length = EI_INIT;
792 static expert_field ei_ieee802154_tap_tlv_padding_not_zeros = EI_INIT;
793 static expert_field ei_ieee802154_tap_tlv_invalid_fcs_type = EI_INIT;
794
795 static int ieee802_15_4_short_address_type = -1;
796 /*
797 * Dissector handles
798 * - beacon dissection is always heuristic.
799 * - the PANID table is for stateful dissectors only (ie: Decode-As)
800 * - otherwise, data dissectors fall back to the heuristic dissectors.
801 */
802 static dissector_table_t panid_dissector_table;
803 static heur_dissector_list_t ieee802154_beacon_subdissector_list;
804 static heur_dissector_list_t ieee802154_heur_subdissector_list;
805
806 /* For the IEs and the vendor specific command */
807 static dissector_table_t header_ie_dissector_table;
808 static dissector_table_t payload_ie_dissector_table;
809 static dissector_table_t mlme_ie_dissector_table;
810 static dissector_table_t cmd_vendor_dissector_table;
811
812 static dissector_handle_t zigbee_ie_handle;
813 static dissector_handle_t zigbee_nwk_handle;
814 static dissector_handle_t ieee802154_handle;
815 static dissector_handle_t ieee802154_nonask_phy_handle;
816 static dissector_handle_t ieee802154_nofcs_handle;
817 static dissector_handle_t ieee802154_tap_handle;
818
819 static int ieee802154_tap = -1;
820
821 /* Handles for MPX-IE the Multiplex ID */
822 static dissector_table_t ethertype_table;
823 static dissector_handle_t eapol_handle;
824 static dissector_handle_t lowpan_handle;
825 static dissector_handle_t wisun_sec_handle;
826
827 /* Versions */
828 static const value_string ieee802154_frame_versions[] = {
829 { IEEE802154_VERSION_2003, "IEEE Std 802.15.4-2003" },
830 { IEEE802154_VERSION_2006, "IEEE Std 802.15.4-2006" },
831 { IEEE802154_VERSION_2015, "IEEE Std 802.15.4-2015" },
832 { IEEE802154_VERSION_RESERVED, "Reserved" },
833 { 0, NULL }
834 };
835
836 /* Name Strings */
837 static const value_string ieee802154_frame_types[] = {
838 { IEEE802154_FCF_BEACON, "Beacon" },
839 { IEEE802154_FCF_DATA, "Data" },
840 { IEEE802154_FCF_ACK, "Ack" },
841 { IEEE802154_FCF_CMD, "Command" },
842 { IEEE802154_FCF_RESERVED, "Reserved" },
843 { IEEE802154_FCF_MULTIPURPOSE, "Multipurpose" },
844 { IEEE802154_FCF_FRAGMENT, "Fragment or Frak" },
845 { IEEE802154_FCF_EXTENDED, "Extended" },
846 { 0, NULL }
847 };
848
849 static const value_string ieee802154_addr_modes[] = {
850 { IEEE802154_FCF_ADDR_NONE, "None" },
851 { IEEE802154_FCF_ADDR_RESERVED, "Reserved" },
852 { IEEE802154_FCF_ADDR_SHORT, "Short/16-bit" },
853 { IEEE802154_FCF_ADDR_EXT, "Long/64-bit" },
854 { 0, NULL }
855 };
856
857 static const value_string ieee802154_cmd_names[] = {
858 { IEEE802154_CMD_ASSOC_REQ, "Association Request" },
859 { IEEE802154_CMD_ASSOC_RSP, "Association Response" },
860 { IEEE802154_CMD_DISASSOC_NOTIFY, "Disassociation Notification" },
861 { IEEE802154_CMD_DATA_RQ, "Data Request" },
862 { IEEE802154_CMD_PANID_CONFLICT, "PAN ID Conflict" },
863 { IEEE802154_CMD_ORPHAN_NOTIFY, "Orphan Notification" },
864 { IEEE802154_CMD_BEACON_REQ, "Beacon Request" },
865 { IEEE802154_CMD_COORD_REALIGN, "Coordinator Realignment" },
866 { IEEE802154_CMD_GTS_REQ, "GTS Request" },
867 { IEEE802154_CMD_TRLE_MGMT_REQ, "TRLE Management Request"},
868 { IEEE802154_CMD_TRLE_MGMT_RSP, "TRLE Management Response"},
869 { IEEE802154_CMD_DSME_ASSOC_REQ, "DSME Association Request"},
870 { IEEE802154_CMD_DSME_ASSOC_RSP, "DSME Association Response"},
871 { IEEE802154_CMD_DSME_GTS_REQ, "DSME GTS Request"},
872 { IEEE802154_CMD_DSME_GTS_RSP, "DSME GTS Response"},
873 { IEEE802154_CMD_DSME_GTS_NOTIFY, "DSME GTS Notify"},
874 { IEEE802154_CMD_DSME_INFO_REQ, "DSME Information Request"},
875 { IEEE802154_CMD_DSME_INFO_RSP, "DSME Information Response"},
876 { IEEE802154_CMD_DSME_BEACON_ALLOC_NOTIFY, "DSME Beacon Allocation Notification"},
877 { IEEE802154_CMD_DSME_BEACON_COLL_NOTIFY, "DSME Beacon Collision Notification"},
878 { IEEE802154_CMD_DSME_LINK_REPORT, "DSME Link Report"},
879 { IEEE802154_CMD_RIT_DATA_REQ, "RIT Data Request"},
880 { IEEE802154_CMD_DBS_REQ, "DBS Request"},
881 { IEEE802154_CMD_DBS_RSP, "DBS Response"},
882 { IEEE802154_CMD_RIT_DATA_RSP, "RIT Data Response"},
883 { IEEE802154_CMD_VENDOR_SPECIFIC, "Vendor Specific"},
884 { 0, NULL }
885 };
886
887 static const value_string ieee802154_sec_level_names[] = {
888 { SECURITY_LEVEL_NONE, "No Security" },
889 { SECURITY_LEVEL_MIC_32, "32-bit Message Integrity Code" },
890 { SECURITY_LEVEL_MIC_64, "64-bit Message Integrity Code" },
891 { SECURITY_LEVEL_MIC_128, "128-bit Message Integrity Code" },
892 { SECURITY_LEVEL_ENC, "Encryption" },
893 { SECURITY_LEVEL_ENC_MIC_32, "Encryption with 32-bit Message Integrity Code" },
894 { SECURITY_LEVEL_ENC_MIC_64, "Encryption with 64-bit Message Integrity Code" },
895 { SECURITY_LEVEL_ENC_MIC_128, "Encryption with 128-bit Message Integrity Code" },
896 { 0, NULL }
897 };
898
899 static const value_string ieee802154_key_id_mode_names[] = {
900 { KEY_ID_MODE_IMPLICIT, "Implicit Key" },
901 { KEY_ID_MODE_KEY_INDEX, "Indexed Key using the Default Key Source" },
902 { KEY_ID_MODE_KEY_EXPLICIT_4, "Explicit Key with 4-octet Key Source" },
903 { KEY_ID_MODE_KEY_EXPLICIT_8, "Explicit Key with 8-octet Key Source" },
904 { 0, NULL }
905 };
906
907 static const true_false_string ieee802154_gts_direction_tfs = {
908 "Receive Only",
909 "Transmit Only"
910 };
911
912 /* The 802.15.4-2003 security suites for the security preferences (only AES-CCM suites are supported). */
913 /* NOTE: The equivalent 2006 security level identifier enumerations are used to simplify 2003 & 2006 integration! */
914 static const enum_val_t ieee802154_2003_sec_suite_enums[] = {
915 { "AES-CCM-128", "AES-128 Encryption, 128-bit Integrity Protection", SECURITY_LEVEL_ENC_MIC_128 },
916 { "AES-CCM-64", "AES-128 Encryption, 64-bit Integrity Protection", SECURITY_LEVEL_ENC_MIC_64 },
917 { "AES-CCM-32", "AES-128 Encryption, 32-bit Integrity Protection", SECURITY_LEVEL_ENC_MIC_32 },
918 { NULL, NULL, 0 }
919 };
920
921 /* Enumeration for key generation */
922 static const value_string ieee802154_key_hash_vals[] = {
923 { KEY_HASH_NONE, "No hash"},
924 { KEY_HASH_ZIP, "ZigBee IP hash" },
925 { KEY_HASH_THREAD, "Thread hash" },
926 { 0, NULL }
927 };
928
929 static const value_string ieee802154_ie_types[] = {
930 { 0, "Header" },
931 { 1, "Payload" },
932 { 0, NULL }
933 };
934
935 static const value_string ieee802154_psie_types[] = {
936 { 0, "Short" },
937 { 1, "Long" },
938 { 0, NULL }
939 };
940
941 static const value_string ieee802154_header_ie_names[] = {
942 { IEEE802154_HEADER_IE_VENDOR_SPECIFIC, "Vendor Specific IE" },
943 { IEEE802154_HEADER_IE_CSL, "CSL IE" },
944 { IEEE802154_HEADER_IE_RIT, "RIT IE" },
945 { IEEE802154_HEADER_IE_DSME_PAN, "DSME PAN descriptor IE" },
946 { IEEE802154_HEADER_IE_RENDEZVOUS, "Rendezvous Time IE" },
947 { IEEE802154_HEADER_IE_TIME_CORR, "Time Correction IE" },
948 { IEEE802154_HEADER_IE_EXT_DSME_PAN, "Extended DSME PAN descriptor IE" },
949 { IEEE802154_HEADER_IE_FSCD, "Fragment Sequence Context Description (FSCD) IE" },
950 { IEEE802154_HEADER_IE_SMPL_SUPER_FRM, "Simplified Superframe Specification IE" },
951 { IEEE802154_HEADER_IE_SMPL_GTS, "Simplified GTS Specification IE" },
952 { IEEE802154_HEADER_IE_LECIM, "LECIM Capabilities IE" },
953 { IEEE802154_HEADER_IE_TRLE, "TRLE Descriptor" },
954 { IEEE802154_HEADER_IE_RCC_CAP, "RCC Capabilities IE" },
955 { IEEE802154_HEADER_IE_RCCN, "RCCN Descriptor IE" },
956 { IEEE802154_HEADER_IE_GLOBAL_TIME, "Global Time IE" },
957 { IEEE802154_HEADER_IE_WISUN, "Wi-SUN IE" },
958 { IEEE802154_HEADER_IE_DA_IE, "DA IE" },
959 { IEEE802154_HEADER_IE_HT1, "Header Termination 1 IE" },
960 { IEEE802154_HEADER_IE_HT2, "Header Termination 2 IE" },
961 { 0, NULL }
962 };
963
964 static const true_false_string hf_ieee802154_nack_tfs = {
965 "Negative Acknowledgement",
966 "Acknowledgement"
967 };
968
969 static const value_string ieee802154_payload_ie_names[] = {
970 { IEEE802154_PAYLOAD_IE_ESDU, "ESDU IE" },
971 { IEEE802154_PAYLOAD_IE_MLME, "MLME IE" },
972 { IEEE802154_PAYLOAD_IE_VENDOR, "Vendor Specific IE" },
973 { IEEE802154_PAYLOAD_IE_MPX, "MPX IE" },
974 { IEEE802154_PAYLOAD_IE_WISUN, "Wi-SUN IE" },
975 { IEEE802154_PAYLOAD_IE_IETF, "IETF IE" },
976 { IEEE802154_PAYLOAD_IE_TERMINATION, "Payload Termination IE" },
977 { 0, NULL }
978 };
979
980 static const value_string ieee802154_psie_names[] = {
981 { IEEE802154_MLME_SUBIE_CHANNEL_HOPPING, "Channel Hopping IE" },
982 { IEEE802154_MLME_SUBIE_TSCH_SYNCH, "TSCH Synchronization IE" },
983 { IEEE802154_MLME_SUBIE_TSCH_SLOTFR_LINK, "TSCH Slotframe and Link IE" },
984 { IEEE802154_MLME_SUBIE_TSCH_TIMESLOT, "TSCH Timeslot IE" },
985 { IEEE802154_MLME_SUBIE_HOPPING_TIMING, "Hopping Timing IE" },
986 { IEEE802154_MLME_SUBIE_ENHANCED_BEACON_FILTER, "Enhanced Beacon Filter IE" },
987 { IEEE802154_MLME_SUBIE_MAC_METRICS, "MAC Metrics IE" },
988 { IEEE802154_MLME_SUBIE_ALL_MAC_METRICS, "All MAC Metrics IE" },
989 { IEEE802154_MLME_SUBIE_COEXISTENCE_SPEC, "Coexistence Specification IE" },
990 { IEEE802154_MLME_SUBIE_SUN_DEVICE_CAPABILITIES, "SUN Device Capabilities IE" },
991 { IEEE802154_MLME_SUBIE_SUN_FSK_GEN_PHY, "SUN FSK Generic PHY IE" },
992 { IEEE802154_MLME_SUBIE_MODE_SWITCH_PARAMETER, "Mode Switch Parameter IE" },
993 { IEEE802154_MLME_SUBIE_PHY_PARAMETER_CHANGE, "PHY Parameter Change IE" },
994 { IEEE802154_MLME_SUBIE_O_QPSK_PHY_MODE, "O-QPSY PHY Mode IE" },
995 { IEEE802154_MLME_SUBIE_PCA_ALLOCATION, "PCA Allocation IE" },
996 { IEEE802154_MLME_SUBIE_DSSS_OPER_MODE, "LECIM DSSS Operating Mode IE"},
997 { IEEE802154_MLME_SUBIE_FSK_OPER_MODE, "LECIM FSK Operating Mode IE" },
998 { IEEE802154_MLME_SUBIE_TVWS_PHY_OPE_MODE, "TVWS PHY Operating Mode Description IE" },
999 { IEEE802154_MLME_SUBIE_TVWS_DEVICE_CAPAB, "TVWS Device Capabilities IE" },
1000 { IEEE802154_MLME_SUBIE_TVWS_DEVICE_CATEG, "TVWS Device Category IE" },
1001 { IEEE802154_MLME_SUBIE_TVWS_DEVICE_IDENTIF, "TVWS Device Identification IE" },
1002 { IEEE802154_MLME_SUBIE_TVWS_DEVICE_LOCATION, "TVWS Device Location IE" },
1003 { IEEE802154_MLME_SUBIE_TVWS_CH_INFOR_QUERY, "TVWS Channel Information Query IE" },
1004 { IEEE802154_MLME_SUBIE_TVWS_CH_INFOR_SOURCE, "TVWS Channel Information Source IE" },
1005 { IEEE802154_MLME_SUBIE_CTM, "CTM IE" },
1006 { IEEE802154_MLME_SUBIE_TIMESTAMP, "Timestamp IE" },
1007 { IEEE802154_MLME_SUBIE_TIMESTAMP_DIFF, "Timestamp Difference IE"},
1008 { IEEE802154_MLME_SUBIE_TMCP_SPECIFICATION, "TMCTP Specification IE" },
1009 { IEEE802154_MLME_SUBIE_RCC_PHY_OPER_MODE, "RCC PHY Operating Mode IE" },
1010 { IEEE802154_IETF_SUBIE_6TOP, "6top IE" },
1011 { 0, NULL }
1012 };
1013
1014 static const value_string zboss_page_names[] = {
1015 { 0, "2.4 GHz" },
1016 { 28, "863-868 MHz band"},
1017 { 29, "868-870, 870-876 MHz band" },
1018 { 30, "870-876 MHz band" },
1019 { 31, "915-921 MHz band" },
1020 { 0, NULL }
1021 };
1022
1023 static const value_string zboss_direction_names[] = {
1024 { 0, "IN" },
1025 { 1, "OUT" },
1026 { 0, NULL }
1027 };
1028
1029 static const value_string tap_tlv_types[] = {
1030 { IEEE802154_TAP_FCS_TYPE, "FCS type"},
1031 { IEEE802154_TAP_RSS, "RSS"},
1032 { IEEE802154_TAP_BIT_RATE, "Bit rate"},
1033 { IEEE802154_TAP_CHANNEL_ASSIGNMENT, "Channel assignment"},
1034 { IEEE802154_TAP_SUN_PHY_INFO, "SUN PHY Information"},
1035 { IEEE802154_TAP_START_OF_FRAME_TS, "Start of frame timestamp"},
1036 { IEEE802154_TAP_END_OF_FRAME_TS, "End of frame timestamp"},
1037 { IEEE802154_TAP_ASN, "Absolute Slot Number (ASN)"},
1038 { IEEE802154_TAP_SLOT_START_TS, "Start of slot timestamp"},
1039 { IEEE802154_TAP_TIMESLOT_LENGTH, "Slot length"},
1040 { IEEE802154_TAP_LQI, "Link Quality Indicator"},
1041 { IEEE802154_TAP_CHANNEL_FREQUENCY, "Channel center frequency"},
1042 { IEEE802154_TAP_CHANNEL_PLAN, "Channel plan"},
1043 { 0, NULL }
1044 };
1045
1046 static const value_string tap_fcs_type_names[] = {
1047 { IEEE802154_FCS_TYPE_NONE, "None" },
1048 { IEEE802154_FCS_TYPE_16_BIT, "ITU-T CRC16" },
1049 { IEEE802154_FCS_TYPE_32_BIT, "ITU-T CRC32" },
1050 { 0, NULL }
1051 };
1052
1053 /* IEEE 802.15.4 Table 7-19 */
1054 static const value_string sun_bands[] = {
1055 { 0, "169 MHz [169.400-169.475]" },
1056 { 1, "450 MHz [450-470]" },
1057 { 2, "470 MHz [470-510]" },
1058 { 3, "780 MHz [779-787]" },
1059 { 4, "863 MHz [863-870]" },
1060 { 5, "896 MHz [896-901]" },
1061 { 6, "901 MHz [901-902]" },
1062 { 7, "915 MHz [902-928]" },
1063 { 8, "917 MHz [917-923.5]" },
1064 { 9, "920 MHz [920-928]" },
1065 { 10, "928 MHz [928-960]" },
1066 { 11, "920 MHz [920-960]" },
1067 { 12, "1427 MHz [1427-1518]" },
1068 { 13, "2450 MHz [2400-2483.5]" },
1069 { 14, "866 MHz [865-867]" },
1070 { 15, "870 MHz [870-876]" },
1071 { 16, "915 MHz-a [902-928 alternate]" },
1072 { 17, "915 MHz-b [902-907.5 & 915-928]" },
1073 { 18, "915 MHz-c [915-928]" },
1074 { 19, "915 MHz-d [915-921]" },
1075 { 20, "915 MHz-e [915-918]" },
1076 { 21, "919 MHz [919-923]" },
1077 { 22, "920 MHz-a [920.5-924.5]" },
1078 { 23, "920 MHz-b [920-925]" },
1079 { 24, "867 MHz [866-869]" },
1080 /* Exegin defined numbers for bands in Table 10-1 but not in Table 7-19 */
1081 { 32, "433 MHz [433.05-434.79]" },
1082 { 33, "868 MHz [868-868.6]" },
1083 { 34, "2380 MHz [2360-2400]" },
1084 { 0, NULL }
1085 };
1086
1087 /* IEEE 802.15.4 Table 7-20 */
1088 static const value_string sun_types[] = {
1089 { IEEE802154_SUN_TYPE_FSK_A, "FSK-A" },
1090 { IEEE802154_SUN_TYPE_FSK_B, "FSK-B" },
1091 { IEEE802154_SUN_TYPE_OQPSK_A, "O-QPSK-A" },
1092 { IEEE802154_SUN_TYPE_OQPSK_B, "O-QPSK-B" },
1093 { IEEE802154_SUN_TYPE_OQPSK_C, "O-QPSK-C" },
1094 { IEEE802154_SUN_TYPE_OFDM_OPT1, "OFDM Option 1" },
1095 { IEEE802154_SUN_TYPE_OFDM_OPT2, "OFDM Option 2" },
1096 { IEEE802154_SUN_TYPE_OFDM_OPT3, "OFDM Option 3" },
1097 { IEEE802154_SUN_TYPE_OFDM_OPT4, "OFDM Option 4" },
1098 { 0, NULL }
1099 };
1100
1101 static const value_string fsk_a_modes[] = {
1102 { 0, "4.8 kb/s; 2-FSK; mod index = 1.0; channel spacing = 12.5 kHz" },
1103 { 1, "9.6 kb/s; 4-FSK; mod index = 0.33; channel spacing = 12.5 kHz" },
1104 { 2, "10 kb/s; 2-FSK; mod index = 0.5; channel spacing = 12.5 kHz" },
1105 { 3, "20 kb/s; 2-FSK; mod index = 0.5; channel spacing = 12.5 kHz" },
1106 { 4, "40 kb/s; 2-FSK; mod index = 0.5; channel spacing = 12.5 kHz" },
1107 { 5, "4.8 kb/s; 2-FSK; mod index = 0.5; channel spacing = 12.5 kHz" },
1108 { 6, "2.4 kb/s; 2-FSK; mod index = 2.0; channel spacing = 12.5 kHz" },
1109 { 7, "9.6 kb/s; 4-FSK; mod index = 0.33; channel spacing = 12.5 kHz" },
1110 { 0, NULL }
1111 };
1112
1113 static const value_string fsk_b_modes[] = {
1114 { 0, "50 kb/s; 2-FSK; mod index = 1.0; channel spacing = 200 kHz" },
1115 { 1, "100 kb/s; 2-FSK; mod index = 1.0; channel spacing = 400 kHz" },
1116 { 2, "150 kb/s; 2-FSK; mod index = 0.5; channel spacing = 400 kHz" },
1117 { 3, "200 kb/s; 2-FSK; mod index = 0.5; channel spacing = 400 kHz" },
1118 { 4, "200 kb/s; 4-FSK; mod index = 0.33; channel spacing = 400 kHz" },
1119 { 5, "200 kb/s; 2-FSK; mod index = 1.0; channel spacing = 600 kHz" },
1120 { 6, "400 kb/s; 4-FSK; mod index = 0.33; channel spacing = 600 kHz" },
1121 { 7, "100 kb/s; 2-FSK; mod index = 0.5; channel spacing = 200 kHz"},
1122 { 8, "50 kb/s; 2-FSK; mod index = 0.5; channel spacing = 100 kHz"},
1123 { 9, "150 kb/s; 2-FSK; mod index = 0.5; channel spacing = 200 kHz"},
1124 { 10, "300 kb/s; 2-FSK; mod index = 0.5; channel spacing = 400 kHz" },
1125 { 0, NULL }
1126 };
1127
1128 static const value_string oqpsk_a_modes[] = {
1129 { 0, "chip rate = 100 kchip/s; SpreadingMode = DSSS; RateMode = 0; data rate = 6.25 kb/s"},
1130 { 1, "chip rate = 100 kchip/s; SpreadingMode = DSSS; RateMode = 1; data rate = 12.5 kb/s"},
1131 { 2, "chip rate = 100 kchip/s; SpreadingMode = DSSS; RateMode = 2; data rate = 25 kb/s"},
1132 { 3, "chip rate = 100 kchip/s; SpreadingMode = DSSS; RateMode = 3; data rate = 50 kb/s"},
1133 { 0, NULL }
1134 };
1135
1136 static const value_string oqpsk_b_modes[] = {
1137 { 0, "chip rate = 1000 kchip/s; SpreadingMode = DSSS; RateMode = 0; data rate = 31.25 kb/s"},
1138 { 1, "chip rate = 1000 kchip/s; SpreadingMode = DSSS; RateMode = 1; data rate = 125 kb/s"},
1139 { 2, "chip rate = 1000 kchip/s; SpreadingMode = DSSS; RateMode = 2; data rate = 250 kb/s"},
1140 { 3, "chip rate = 1000 kchip/s; SpreadingMode = DSSS; RateMode = 3; data rate = 500 kb/s"},
1141 { 4, "chip rate = 1000 kchip/s; SpreadingMode = MDSSS; RateMode = 0; data rate = 62.5 kb/s"},
1142 { 5, "chip rate = 1000 kchip/s; SpreadingMode = MDSSS; RateMode = 1; data rate = 125 kb/s"},
1143 { 6, "chip rate = 1000 kchip/s; SpreadingMode = MDSSS; RateMode = 2; data rate = 250 kb/s"},
1144 { 7, "chip rate = 1000 kchip/s; SpreadingMode = MDSSS; RateMode = 3; data rate = 500 kb/s"},
1145 { 0, NULL }
1146 };
1147
1148 static const value_string oqpsk_c_modes[] = {
1149 { 0, "chip rate = 2000 kchip/s; SpreadingMode = DSSS; RateMode = 0; data rate = 31.25 kb/s"},
1150 { 1, "chip rate = 2000 kchip/s; SpreadingMode = DSSS; RateMode = 1; data rate = 125 kb/s"},
1151 { 2, "chip rate = 2000 kchip/s; SpreadingMode = DSSS; RateMode = 2; data rate = 250 kb/s"},
1152 { 3, "chip rate = 2000 kchip/s; SpreadingMode = DSSS; RateMode = 3; data rate = 500 kb/s"},
1153 { 4, "chip rate = 2000 kchip/s; SpreadingMode = MDSSS; RateMode = 0; data rate = 62.5 kb/s"},
1154 { 5, "chip rate = 2000 kchip/s; SpreadingMode = MDSSS; RateMode = 1; data rate = 125 kb/s"},
1155 { 6, "chip rate = 2000 kchip/s; SpreadingMode = MDSSS; RateMode = 2; data rate = 250 kb/s"},
1156 { 7, "chip rate = 2000 kchip/s; SpreadingMode = MDSSS; RateMode = 3; data rate = 500 kb/s"},
1157 { 0, NULL }
1158 };
1159
1160 static const value_string ofdm_modes[] = {
1161 { 0, "MCS0" },
1162 { 1, "MCS1" },
1163 { 2, "MCS2" },
1164 { 3, "MCS3" },
1165 { 4, "MCS4" },
1166 { 5, "MCS5" },
1167 { 6, "MCS6" },
1168 { 0, NULL },
1169 };
1170
1171 static const value_string channel_page_names[] = {
1172 { 0, "Default" },
1173 { 1, "ASK" },
1174 { 2, "O-QPSK" },
1175 { 3, "CSS" },
1176 { 4, "HRP UWB" },
1177 { 5, "780 MHz" },
1178 { 6, "GFSK" },
1179 { 7, "MSK" },
1180 { 8, "LRP_UWB" },
1181 { 9, "SUN" },
1182 { 10, "SUN FSK" },
1183 { 11, "2380 MHz" },
1184 { 12, "LECIM" },
1185 { 13, "RCC" },
1186 { 0, NULL }
1187 };
1188
1189 static const value_string ietf_6top_types[] = {
1190 { IETF_6TOP_TYPE_REQUEST, "Request" },
1191 { IETF_6TOP_TYPE_RESPONSE, "Response" },
1192 { IETF_6TOP_TYPE_CONFIRMATION, "Confirmation" },
1193 { 0, NULL }
1194 };
1195
1196 static const value_string ietf_6top_command_identifiers[] = {
1197 { IETF_6TOP_CMD_ADD, "ADD" },
1198 { IETF_6TOP_CMD_DELETE, "DELETE" },
1199 { IETF_6TOP_CMD_RELOCATE, "RELOCATE" },
1200 { IETF_6TOP_CMD_COUNT, "COUNT" },
1201 { IETF_6TOP_CMD_LIST, "LIST" },
1202 { IETF_6TOP_CMD_SIGNAL, "SIGNAL" },
1203 { IETF_6TOP_CMD_CLEAR, "CLEAR" },
1204 { 0, NULL }
1205 };
1206
1207 static const value_string ietf_6top_return_codes[] = {
1208 { IETF_6TOP_RC_SUCCESS, "SUCCESS" },
1209 { IETF_6TOP_RC_EOL, "RC_EOL" },
1210 { IETF_6TOP_RC_ERR, "RC_ERR" },
1211 { IETF_6TOP_RC_RESET, "RC_RESET" },
1212 { IETF_6TOP_RC_ERR_VERSION, "RC_ERR_VERSION" },
1213 { IETF_6TOP_RC_ERR_SFID, "RC_ERR_SFID" },
1214 { IETF_6TOP_RC_ERR_SEQNUM, "RC_ERR_SEQNUM" },
1215 { IETF_6TOP_RC_ERR_CELLLIST, "RC_ERR_CELLLIST" },
1216 { IETF_6TOP_RC_ERR_BUSY, "RC_ERR_BUSY" },
1217 { IETF_6TOP_RC_ERR_LOCKED, "RC_ERR_LOCKED" },
1218 { 0, NULL }
1219 };
1220
1221 static const value_string ietf_6top_cell_options[] = {
1222 { 0, "ALL" },
1223 { 1, "TX" },
1224 { 2, "RX" },
1225 { 3, "TX|RX" },
1226 { 4, "SHARED" },
1227 { 5, "TX|SHARED" },
1228 { 6, "RX|SHARED" },
1229 { 7, "TX|RX|SHARED" },
1230 { 0, NULL}
1231 };
1232
1233 static const value_string mpx_transfer_type_vals[] = {
1234 { IEEE802159_MPX_FULL_FRAME, "Full Frame" },
1235 { IEEE802159_MPX_FULL_FRAME_NO_MUXID, "Full frame with compressed Multiplex ID" },
1236 { IEEE802159_MPX_NON_LAST_FRAGMENT, "Non-last Fragment" },
1237 { IEEE802159_MPX_LAST_FRAGMENT, "Last Fragment" },
1238 { IEEE802159_MPX_ABORT, "Abort" },
1239 { 0, NULL }
1240 };
1241
1242 static const value_string mpx_multiplex_id_vals[] = {
1243 { IEEE802159_MPX_MULTIPLEX_ID_KMP, "KMP" },
1244 { IEEE802159_MPX_MULTIPLEX_ID_WISUN, "Wi-SUN" },
1245 { 0, NULL }
1246 };
1247
1248 // used by the Wi-SUN dissector
1249 const value_string ieee802154_mpx_kmp_id_vals[] = {
1250 { IEEE802159_MPX_KMP_ID_IEEE8021X, "IEEE 802.1X/MKA" },
1251 { IEEE802159_MPX_KMP_ID_HIP, "HIP" },
1252 { IEEE802159_MPX_KMP_ID_IKEV2, "IKEv2" },
1253 { IEEE802159_MPX_KMP_ID_PANA, "PANA" },
1254 { IEEE802159_MPX_KMP_ID_DRAGONFLY, "Dragonfly" },
1255 { IEEE802159_MPX_KMP_ID_IEEE80211_4WH, "IEEE 802.11/4WH" },
1256 { IEEE802159_MPX_KMP_ID_IEEE80211_GKH, "IEEE 802.11/GKH" },
1257 { IEEE802159_MPX_KMP_ID_ETSI_TS_102_887_2, "ETSI TS 102 887-2" },
1258 { IEEE802159_MPX_KMP_ID_VENDOR_SPECIFIC, "Vendor-specific" },
1259 { 0, NULL }
1260 };
1261
1262 static const value_string mpx_wisun_subid_vals[] = {
1263 { IEEE802159_MPX_WISUN_SUBID_MHDS, "WM-MHDS" },
1264 { IEEE802159_MPX_WISUN_SUBID_6LOWPAN, "WM-6LO" },
1265 { IEEE802159_MPX_WISUN_SUBID_SECURITY, "WM-SEC" },
1266 { 0, NULL }
1267 };
1268
1269 /* Preferences for 2003 security */
1270 static gint ieee802154_sec_suite = SECURITY_LEVEL_ENC_MIC_64;
1271 static gboolean ieee802154_extend_auth = TRUE;
1272
1273 /* Macro to check addressing, and throw a warning flag if incorrect. */
1274 #define IEEE802154_CMD_ADDR_CHECK(_pinfo_, _item_, _cmdid_, _x_) \
1275 if (!(_x_)) \
1276 expert_add_info_format(_pinfo_, _item_, &ei_ieee802154_invalid_addressing, \
1277 "Invalid Addressing for %s", \
1278 val_to_str_const(_cmdid_, ieee802154_cmd_names, "Unknown Command"))
1279
1280 /* CRC definitions. IEEE 802.15.4 CRCs vary from ITU-T by using an initial value of
1281 * 0x0000, and no XOR out. IEEE802154_CRC_XOR is defined as 0xFFFF in order to un-XOR
1282 * the output from the ITU-T (CCITT) CRC routines in Wireshark.
1283 */
1284 #define IEEE802154_CRC_SEED 0x0000
1285 #define IEEE802154_CRC_XOROUT 0xFFFF
1286 #define ieee802154_crc_tvb(tvb, offset) (crc16_ccitt_tvb_seed(tvb, offset, IEEE802154_CRC_SEED) ^ IEEE802154_CRC_XOROUT)
1287
1288 /* For the 32-bit CRC, IEEE 802.15.4 uses ITU-T (CCITT) CRC-32. */
1289 #define ieee802154_crc32_tvb(tvb, offset) (crc32_ccitt_tvb(tvb, offset))
1290
ieee802_15_4_short_address_to_str(const address * addr,gchar * buf,int buf_len)1291 static int ieee802_15_4_short_address_to_str(const address* addr, gchar *buf, int buf_len)
1292 {
1293 guint16 ieee_802_15_4_short_addr = pletoh16(addr->data);
1294
1295 if (ieee_802_15_4_short_addr == 0xffff)
1296 {
1297 (void) g_strlcpy(buf, "Broadcast", buf_len);
1298 return 10;
1299 }
1300
1301 *buf++ = '0';
1302 *buf++ = 'x';
1303 buf = word_to_hex(buf, ieee_802_15_4_short_addr);
1304 *buf = '\0'; /* NULL terminate */
1305
1306 return 7;
1307 }
1308
ieee802_15_4_short_address_str_len(const address * addr _U_)1309 static int ieee802_15_4_short_address_str_len(const address* addr _U_)
1310 {
1311 return 11;
1312 }
1313
ieee802_15_4_short_address_len(void)1314 static int ieee802_15_4_short_address_len(void)
1315 {
1316 return 2;
1317 }
1318
1319 /* ======================================================================= */
_find_or_create_conversation(packet_info * pinfo,const address * src_addr,const address * dst_addr)1320 static conversation_t *_find_or_create_conversation(packet_info *pinfo, const address *src_addr, const address *dst_addr)
1321 {
1322 conversation_t *conv = NULL;
1323
1324 /* Have we seen this conversation before? */
1325 conv = find_conversation(pinfo->num, src_addr, dst_addr, ENDPOINT_NONE, 0, 0, 0);
1326 if (conv == NULL) {
1327 /* No, this is a new conversation. */
1328 conv = conversation_new(pinfo->num, src_addr, dst_addr, ENDPOINT_NONE, 0, 0, 0);
1329 }
1330 return conv;
1331 }
1332
1333 /* ======================================================================= */
transaction_start(packet_info * pinfo,proto_tree * tree,const ieee802154_packet * packet,guint32 * key)1334 static ieee802154_transaction_t *transaction_start(packet_info *pinfo, proto_tree *tree, const ieee802154_packet *packet, guint32 *key)
1335 {
1336 ieee802154_transaction_t *ieee802154_trans;
1337 wmem_tree_key_t ieee802154_key[3];
1338 proto_item *it;
1339
1340 if (!PINFO_FD_VISITED(pinfo)) {
1341 /*
1342 * This is a new request, create a new transaction structure and map it
1343 * to the unmatched table.
1344 */
1345 ieee802154_key[0].length = 2;
1346 ieee802154_key[0].key = key;
1347 ieee802154_key[1].length = 0;
1348 ieee802154_key[1].key = NULL;
1349
1350 ieee802154_trans = wmem_new0(wmem_file_scope(), ieee802154_transaction_t);
1351
1352 if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT)
1353 ieee802154_trans->dst16 = packet->dst16;
1354 else if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT)
1355 ieee802154_trans->dst64 = packet->dst64;
1356 ieee802154_trans->dst_addr_mode = packet->dst_addr_mode;
1357
1358 if (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT)
1359 ieee802154_trans->src16 = packet->src16;
1360 else if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT)
1361 ieee802154_trans->src64 = packet->src64;
1362 ieee802154_trans->src_addr_mode = packet->src_addr_mode;
1363
1364 if (packet->dst_pan_present) {
1365 ieee802154_trans->dst_pan_present = TRUE;
1366 ieee802154_trans->dst_pan = packet->dst_pan;
1367 }
1368 if (packet->src_pan_present) {
1369 ieee802154_trans->src_pan_present = TRUE;
1370 ieee802154_trans->src_pan = packet->src_pan;
1371 }
1372 ieee802154_trans->rqst_frame = pinfo->num;
1373 ieee802154_trans->ack_frame = 0;
1374 ieee802154_trans->rqst_time = pinfo->abs_ts;
1375 nstime_set_unset(&ieee802154_trans->ack_time);
1376 wmem_tree_insert32_array(transaction_unmatched_pdus, ieee802154_key, (void *)ieee802154_trans);
1377 } else {
1378 /* Already visited this frame */
1379 guint32 frame_num = pinfo->num;
1380
1381 ieee802154_key[0].length = 2;
1382 ieee802154_key[0].key = key;
1383 ieee802154_key[1].length = 1;
1384 ieee802154_key[1].key = &frame_num;
1385 ieee802154_key[2].length = 0;
1386 ieee802154_key[2].key = NULL;
1387
1388 ieee802154_trans = (ieee802154_transaction_t *)wmem_tree_lookup32_array(transaction_matched_pdus, ieee802154_key);
1389
1390 if (!ieee802154_trans) {
1391 /* No ACK found - add field and expert info */
1392 it = proto_tree_add_item(tree, hf_ieee802154_no_ack, NULL, 0, 0, ENC_NA);
1393 proto_item_set_generated(it);
1394
1395 expert_add_info_format(pinfo, it, &ei_ieee802154_ack_not_found, "No ack found to request in frame %u", pinfo->num);
1396
1397 return NULL;
1398 }
1399 }
1400
1401 /* Print state tracking in the tree */
1402 if (ieee802154_trans->ack_frame) {
1403 it = proto_tree_add_uint(tree, hf_ieee802154_ack_in, NULL, 0, 0, ieee802154_trans->ack_frame);
1404 proto_item_set_generated(it);
1405 }
1406
1407 return ieee802154_trans;
1408 } /* transaction_start() */
1409
transaction_end(packet_info * pinfo,proto_tree * tree,const ieee802154_packet * packet,guint32 * key)1410 static ieee802154_transaction_t *transaction_end(packet_info *pinfo, proto_tree *tree, const ieee802154_packet *packet, guint32 *key)
1411 {
1412 ieee802154_transaction_t *ieee802154_trans = NULL;
1413 wmem_tree_key_t ieee802154_key[3];
1414 proto_item *it;
1415
1416 if (!PINFO_FD_VISITED(pinfo)) {
1417 guint32 frame_num;
1418 nstime_t ns;
1419
1420 ieee802154_key[0].length = 2;
1421 ieee802154_key[0].key = key;
1422 ieee802154_key[1].length = 0;
1423 ieee802154_key[1].key = NULL;
1424
1425 ieee802154_trans = (ieee802154_transaction_t *)wmem_tree_lookup32_array(transaction_unmatched_pdus, ieee802154_key);
1426 if (ieee802154_trans == NULL)
1427 return NULL;
1428
1429 /* we have already seen this response, or an identical one */
1430 if (ieee802154_trans->ack_frame != 0)
1431 return NULL;
1432
1433 /* If addresses are present they must match */
1434 if (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
1435 if (packet->src16 != ieee802154_trans->dst16)
1436 return NULL;
1437 }
1438 else if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
1439 if (packet->src64 != ieee802154_trans->dst64)
1440 return NULL;
1441 }
1442 if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
1443 if (packet->dst16 != ieee802154_trans->src16)
1444 return NULL;
1445 }
1446 else if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) {
1447 if (packet->dst64 != ieee802154_trans->src64)
1448 return NULL;
1449 }
1450
1451 nstime_delta(&ns, &pinfo->abs_ts, &ieee802154_trans->rqst_time);
1452 if (nstime_cmp(&ns, &ieee802154_transaction_timeout) > 0)
1453 return NULL;
1454
1455 ieee802154_trans->ack_time = ns;
1456 ieee802154_trans->ack_frame = pinfo->num;
1457
1458 /*
1459 * We found a match. Add entries to the matched table for both
1460 * request and ack frames
1461 */
1462 ieee802154_key[0].length = 2;
1463 ieee802154_key[0].key = key;
1464 ieee802154_key[1].length = 1;
1465 ieee802154_key[1].key = &frame_num;
1466 ieee802154_key[2].length = 0;
1467 ieee802154_key[2].key = NULL;
1468
1469 frame_num = ieee802154_trans->rqst_frame;
1470 wmem_tree_insert32_array(transaction_matched_pdus, ieee802154_key, (void *)ieee802154_trans);
1471
1472 frame_num = ieee802154_trans->ack_frame;
1473 wmem_tree_insert32_array(transaction_matched_pdus, ieee802154_key, (void *)ieee802154_trans);
1474 } else {
1475 /* Already visited this frame */
1476 guint32 frame_num = pinfo->num;
1477
1478 ieee802154_key[0].length = 2;
1479 ieee802154_key[0].key = key;
1480 ieee802154_key[1].length = 1;
1481 ieee802154_key[1].key = &frame_num;
1482 ieee802154_key[2].length = 0;
1483 ieee802154_key[2].key = NULL;
1484
1485 ieee802154_trans = (ieee802154_transaction_t *)wmem_tree_lookup32_array(transaction_matched_pdus, ieee802154_key);
1486
1487 if (!ieee802154_trans) {
1488 /* No ack request found - add field and expert info */
1489 it = proto_tree_add_item(tree, hf_ieee802154_no_ack_request, NULL, 0, 0, ENC_NA);
1490 proto_item_set_generated(it);
1491
1492 expert_add_info_format(pinfo, it, &ei_ieee802154_ack_request_not_found, "No request found to ack in frame %u", pinfo->num);
1493 return NULL;
1494 }
1495 }
1496
1497 if (packet->dst_pan_present == FALSE) {
1498 if (ieee802154_trans->src_pan_present) {
1499 it = proto_tree_add_uint(tree, hf_ieee802154_dst_panID, NULL, 0, 0, ieee802154_trans->src_pan);
1500 proto_item_set_generated(it);
1501 }
1502 else if (ieee802154_trans->dst_pan_present) {
1503 it = proto_tree_add_uint(tree, hf_ieee802154_dst_panID, NULL, 0, 0, ieee802154_trans->dst_pan);
1504 proto_item_set_generated(it);
1505 }
1506 }
1507 if ((packet->src_pan_present == FALSE) && (ieee802154_trans->src_pan_present) && (ieee802154_trans->dst_pan_present)) {
1508 it = proto_tree_add_uint(tree, hf_ieee802154_src_panID, NULL, 0, 0, ieee802154_trans->dst_pan);
1509 proto_item_set_generated(it);
1510 }
1511
1512 if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) {
1513 if (ieee802154_trans->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
1514 it = proto_tree_add_uint(tree, hf_ieee802154_dst16, NULL, 0, 0, ieee802154_trans->src16);
1515 proto_item_set_generated(it);
1516
1517 it = proto_tree_add_uint(tree, hf_ieee802154_addr16, NULL, 0, 0, ieee802154_trans->src16);
1518 proto_item_set_hidden(it);
1519 proto_item_set_generated(it);
1520 }
1521 else if (ieee802154_trans->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
1522 it = proto_tree_add_eui64(tree, hf_ieee802154_dst64, NULL, 0, 0, ieee802154_trans->src64);
1523 proto_item_set_generated(it);
1524
1525 it = proto_tree_add_eui64(tree, hf_ieee802154_addr64, NULL, 0, 0, ieee802154_trans->src64);
1526 proto_item_set_hidden(it);
1527 proto_item_set_generated(it);
1528 }
1529 }
1530
1531 if (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE) {
1532 if (ieee802154_trans->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
1533 it = proto_tree_add_uint(tree, hf_ieee802154_src16, NULL, 0, 0, ieee802154_trans->dst16);
1534 proto_item_set_generated(it);
1535
1536 it = proto_tree_add_uint(tree, hf_ieee802154_addr16, NULL, 0, 0, ieee802154_trans->dst16);
1537 proto_item_set_hidden(it);
1538 proto_item_set_generated(it);
1539 }
1540 else if (ieee802154_trans->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) {
1541 it = proto_tree_add_eui64(tree, hf_ieee802154_src64, NULL, 0, 0, ieee802154_trans->dst64);
1542 proto_item_set_generated(it);
1543
1544 it = proto_tree_add_eui64(tree, hf_ieee802154_addr64, NULL, 0, 0, ieee802154_trans->dst64);
1545 proto_item_set_hidden(it);
1546 proto_item_set_generated(it);
1547 }
1548 }
1549
1550 /* Print state tracking in the tree */
1551 it = proto_tree_add_uint(tree, hf_ieee802154_ack_to, NULL, 0, 0, ieee802154_trans->rqst_frame);
1552 proto_item_set_generated(it);
1553
1554 it = proto_tree_add_time(tree, hf_ieee802154_ack_time, NULL, 0, 0, &ieee802154_trans->ack_time);
1555 proto_item_set_generated(it);
1556
1557 return ieee802154_trans;
1558
1559 } /* transaction_end() */
1560
1561 /**
1562 * Dissector helper, parses and displays the frame control field.
1563 *
1564 * @param tvb pointer to buffer containing raw packet.
1565 * @param pinfo pointer to packet information fields
1566 * @param tree pointer to data tree wireshark uses to display packet.
1567 * @param packet IEEE 802.15.4 packet information.
1568 * @param offset offset into the tvb to find the FCF.
1569 *
1570 */
1571 static void
dissect_ieee802154_fcf(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,ieee802154_packet * packet,guint * offset)1572 dissect_ieee802154_fcf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet, guint *offset)
1573 {
1574 guint16 fcf;
1575 static int * const ieee802154_fields[] = {
1576 &hf_ieee802154_frame_type,
1577 &hf_ieee802154_security,
1578 &hf_ieee802154_pending,
1579 &hf_ieee802154_ack_request,
1580 &hf_ieee802154_pan_id_compression,
1581 &hf_ieee802154_fcf_reserved,
1582 &hf_ieee802154_seqno_suppression,
1583 &hf_ieee802154_ie_present,
1584 &hf_ieee802154_dst_addr_mode,
1585 &hf_ieee802154_version,
1586 &hf_ieee802154_src_addr_mode,
1587 NULL
1588 };
1589
1590 static int* const ieee802154_mpf_short_fields[] = {
1591 &hf_ieee802154_frame_type,
1592 &hf_ieee802154_mpf_long_frame_control,
1593 &hf_ieee802154_mpf_dst_addr_mode,
1594 &hf_ieee802154_mpf_src_addr_mode,
1595 NULL
1596 };
1597
1598 static int* const ieee802154_mpf_long_fields[] = {
1599 &hf_ieee802154_frame_type,
1600 &hf_ieee802154_mpf_long_frame_control,
1601 &hf_ieee802154_mpf_dst_addr_mode,
1602 &hf_ieee802154_mpf_src_addr_mode,
1603 &hf_ieee802154_mpf_pan_id_present,
1604 &hf_ieee802154_mpf_security,
1605 &hf_ieee802154_mpf_seqno_suppression,
1606 &hf_ieee802154_mpf_pending,
1607 &hf_ieee802154_mpf_version,
1608 &hf_ieee802154_mpf_ack_request,
1609 &hf_ieee802154_mpf_ie_present,
1610 NULL
1611 };
1612
1613 /* Get the FCF field. */
1614 fcf = tvb_get_letohs(tvb, *offset);
1615
1616 /* Parse FCF Flags. */
1617 packet->frame_type = (fcf & IEEE802154_FCF_TYPE_MASK);
1618
1619 if (packet->frame_type == IEEE802154_FCF_MULTIPURPOSE) {
1620 /* Multipurpose frames use a different 1 or 2 byte FCF */
1621 packet->long_frame_control = (fcf & IEEE802154_MPF_FCF_LONG_FC) >> 3;
1622 packet->dst_addr_mode = (fcf & IEEE802154_MPF_FCF_DADDR_MASK) >> 4;
1623 packet->src_addr_mode = (fcf & IEEE802154_MPF_FCF_SADDR_MASK) >> 6;
1624
1625 /* The second octet of the FCF is only present if the long frame control bit is set */
1626 if (packet->long_frame_control) {
1627 packet->pan_id_present = (fcf & IEEE802154_MPF_FCF_PAN_ID_PRESENT) >> 8;
1628 packet->security_enable = (fcf & IEEE802154_MPF_FCF_SEC_EN) >> 9;
1629 packet->seqno_suppression = (fcf & IEEE802154_MPF_FCF_SEQNO_SUPPRESSION) >> 10;
1630 packet->frame_pending = (fcf & IEEE802154_MPF_FCF_FRAME_PND) >> 11;
1631 packet->version = (fcf & IEEE802154_MPF_FCF_VERSION) >> 12;
1632 packet->ack_request = (fcf & IEEE802154_MPF_FCF_ACK_REQ) >> 14;
1633 packet->ie_present = (fcf & IEEE802154_MPF_FCF_IE_PRESENT) >> 15;
1634 }
1635 else {
1636 packet->security_enable = FALSE;
1637 packet->seqno_suppression = FALSE;
1638 packet->frame_pending = FALSE;
1639 packet->version = 0;
1640 packet->ack_request = FALSE;
1641 packet->ie_present = FALSE;
1642 }
1643
1644 if (ieee802154e_compatibility) {
1645 if (((tvb_reported_length(tvb) == IEEE802154E_LE_WUF_LEN)) && !packet->long_frame_control) {
1646 /* Check if this is an IEEE 802.15.4e LE-multipurpose Wake-up Frame, which has a single-octet FCF
1647 * and a static layout that cannot be inferred from the FCF alone. */
1648 guint16 ie_header = tvb_get_letohs(tvb, (*offset) + 6);
1649 guint16 id = (guint16)((ie_header & IEEE802154_HEADER_IE_ID_MASK) >> 7);
1650 guint16 length = (guint16)(ie_header & IEEE802154_HEADER_IE_LENGTH_MASK);
1651 if ((id == IEEE802154_HEADER_IE_RENDEZVOUS) && (length == 2)) {
1652 /* This appears to be a WUF, as identified by containing a single
1653 * Rendezvous Time Header IE with only a rendezvous time. */
1654 packet->ie_present = TRUE;
1655 packet->pan_id_present = TRUE;
1656 }
1657 }
1658 }
1659 }
1660 else {
1661 /* Standard 802.15.4 FCF */
1662 packet->security_enable = (fcf & IEEE802154_FCF_SEC_EN) >> 3;
1663 packet->frame_pending = (fcf & IEEE802154_FCF_FRAME_PND) >> 4;
1664 packet->ack_request = (fcf & IEEE802154_FCF_ACK_REQ) >> 5;
1665 packet->pan_id_compression = (fcf & IEEE802154_FCF_PAN_ID_COMPRESSION) >> 6;
1666 /* bit 7 reserved */
1667 packet->seqno_suppression = (fcf & IEEE802154_FCF_SEQNO_SUPPRESSION) >> 8;
1668 packet->ie_present = (fcf & IEEE802154_FCF_IE_PRESENT) >> 9;
1669 packet->dst_addr_mode = (fcf & IEEE802154_FCF_DADDR_MASK) >> 10;
1670 packet->version = (fcf & IEEE802154_FCF_VERSION) >> 12;
1671 packet->src_addr_mode = (fcf & IEEE802154_FCF_SADDR_MASK) >> 14;
1672 }
1673
1674 if ((packet->version == IEEE802154_VERSION_2015) && (packet->frame_type == IEEE802154_FCF_BEACON)) {
1675 proto_item_append_text(tree, " Enhanced Beacon");
1676 col_set_str(pinfo->cinfo, COL_INFO, "Enhanced Beacon");
1677 }
1678 else {
1679 proto_item_append_text(tree, " %s", val_to_str_const(packet->frame_type, ieee802154_frame_types, "Reserved"));
1680 col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet->frame_type, ieee802154_frame_types, "Reserved"));
1681 }
1682
1683 if (packet->frame_type == IEEE802154_FCF_MULTIPURPOSE) {
1684 if (packet->long_frame_control) {
1685 proto_tree_add_bitmask(tree, tvb, *offset, hf_ieee802154_fcf,
1686 ett_ieee802154_fcf, ieee802154_mpf_long_fields, ENC_LITTLE_ENDIAN);
1687 *offset += 2;
1688 }
1689 else {
1690 proto_tree_add_bitmask_len(tree, tvb, *offset, 1, hf_ieee802154_fcf,
1691 ett_ieee802154_fcf, ieee802154_mpf_short_fields,
1692 &ei_ieee802154_fcs_bitmask_len, ENC_LITTLE_ENDIAN);
1693 *offset += 1;
1694 }
1695 }
1696 else {
1697 proto_tree_add_bitmask(tree, tvb, *offset, hf_ieee802154_fcf,
1698 ett_ieee802154_fcf, ieee802154_fields, ENC_LITTLE_ENDIAN);
1699 *offset += 2;
1700 }
1701
1702 } /* dissect_ieee802154_fcf */
1703
register_ieee802154_mac_key_hash_handler(guint hash_identifier,ieee802154_set_key_func key_func)1704 void register_ieee802154_mac_key_hash_handler(guint hash_identifier, ieee802154_set_key_func key_func)
1705 {
1706 /* Ensure no duplication */
1707 DISSECTOR_ASSERT(wmem_tree_lookup32(mac_key_hash_handlers, hash_identifier) == NULL);
1708
1709 wmem_tree_insert32(mac_key_hash_handlers, hash_identifier, (void*)key_func);
1710 }
1711
dissect_ieee802154_aux_sec_header_and_key(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,ieee802154_packet * packet,guint * offset)1712 void dissect_ieee802154_aux_sec_header_and_key(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, ieee802154_packet *packet, guint *offset)
1713 {
1714 proto_tree *field_tree, *header_tree;
1715 proto_item *ti, *hidden_item;
1716 guint8 security_control;
1717 guint aux_length = 1; /* Minimum length of the auxiliary header. */
1718 static int * const security_fields[] = {
1719 &hf_ieee802154_aux_sec_security_level,
1720 &hf_ieee802154_aux_sec_key_id_mode,
1721 &hf_ieee802154_aux_sec_frame_counter_suppression,
1722 &hf_ieee802154_aux_sec_asn_in_nonce,
1723 &hf_ieee802154_aux_sec_reserved,
1724 NULL
1725 };
1726
1727 /* Parse the security control field. */
1728 security_control = tvb_get_guint8(tvb, *offset);
1729 packet->security_level = (ieee802154_security_level)(security_control & IEEE802154_AUX_SEC_LEVEL_MASK);
1730 packet->key_id_mode = (ieee802154_key_id_mode)((security_control & IEEE802154_AUX_KEY_ID_MODE_MASK) >> IEEE802154_AUX_KEY_ID_MODE_SHIFT);
1731 if (packet->version == IEEE802154_VERSION_2015) {
1732 packet->frame_counter_suppression = security_control & IEEE802154_AUX_FRAME_COUNTER_SUPPRESSION_MASK ? TRUE : FALSE;
1733 }
1734
1735 /* Compute the length of the auxiliary header and create a subtree. */
1736 if (!packet->frame_counter_suppression) aux_length += 4;
1737 if (packet->key_id_mode != KEY_ID_MODE_IMPLICIT) aux_length++;
1738 if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_4) aux_length += 4;
1739 if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_8) aux_length += 8;
1740
1741 ti = proto_tree_add_item(tree, hf_ieee802154_aux_security_header, tvb, *offset, aux_length, ENC_NA);
1742 header_tree = proto_item_add_subtree(ti, ett_ieee802154_auxiliary_security);
1743
1744 /* Security Control Field */
1745 proto_tree_add_bitmask(header_tree, tvb, *offset, hf_ieee802154_aux_sec_security_control, ett_ieee802154_aux_sec_control, security_fields, ENC_NA);
1746 (*offset)++;
1747
1748 /* Frame Counter Field */
1749 if (!packet->frame_counter_suppression) {
1750 proto_tree_add_item_ret_uint(header_tree, hf_ieee802154_aux_sec_frame_counter, tvb, *offset, 4, ENC_LITTLE_ENDIAN, &packet->frame_counter);
1751 (*offset) += 4;
1752 }
1753 else {
1754 packet->asn = ieee802154_tsch_asn;
1755 }
1756
1757 /* Key identifier field(s). */
1758 if (packet->key_id_mode != KEY_ID_MODE_IMPLICIT) {
1759 /* Create a subtree. */
1760 field_tree = proto_tree_add_subtree(header_tree, tvb, *offset, 1,
1761 ett_ieee802154_aux_sec_key_id, &ti, "Key Identifier Field"); /* Will fix length later. */
1762 /* Add key source, if it exists. */
1763 if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_4) {
1764 packet->key_source.addr32 = tvb_get_ntohl(tvb, *offset);
1765 proto_tree_add_uint64(field_tree, hf_ieee802154_aux_sec_key_source, tvb, *offset, 4, packet->key_source.addr32);
1766 hidden_item = proto_tree_add_item(field_tree, hf_ieee802154_aux_sec_key_source_bytes, tvb, *offset, 4, ENC_NA);
1767 proto_item_set_hidden(hidden_item);
1768 proto_item_set_len(ti, 1 + 4);
1769 (*offset) += 4;
1770 }
1771 if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_8) {
1772 packet->key_source.addr64 = tvb_get_ntoh64(tvb, *offset);
1773 proto_tree_add_uint64(field_tree, hf_ieee802154_aux_sec_key_source, tvb, *offset, 8, packet->key_source.addr64);
1774 hidden_item = proto_tree_add_item(field_tree, hf_ieee802154_aux_sec_key_source_bytes, tvb, *offset, 8, ENC_NA);
1775 proto_item_set_hidden(hidden_item);
1776 proto_item_set_len(ti, 1 + 8);
1777 (*offset) += 8;
1778 }
1779 /* Add key identifier. */
1780 packet->key_index = tvb_get_guint8(tvb, *offset);
1781 proto_tree_add_uint(field_tree, hf_ieee802154_aux_sec_key_index, tvb, *offset, 1, packet->key_index);
1782 (*offset)++;
1783 }
1784 }
1785
decrypt_ieee802154_payload(tvbuff_t * tvb,guint offset,packet_info * pinfo,proto_tree * key_tree,ieee802154_packet * packet,ieee802154_decrypt_info_t * decrypt_info,ieee802154_set_key_func set_key_func,ieee802154_decrypt_func decrypt_func)1786 tvbuff_t *decrypt_ieee802154_payload(tvbuff_t * tvb, guint offset, packet_info * pinfo, proto_tree* key_tree,
1787 ieee802154_packet * packet, ieee802154_decrypt_info_t* decrypt_info,
1788 ieee802154_set_key_func set_key_func, ieee802154_decrypt_func decrypt_func)
1789 {
1790 proto_item* ti;
1791 unsigned char key[IEEE802154_CIPHER_SIZE];
1792 unsigned char alt_key[IEEE802154_CIPHER_SIZE];
1793 tvbuff_t * payload_tvb = NULL;
1794
1795 /* Lookup the key. */
1796 for (decrypt_info->key_number = 0; decrypt_info->key_number < num_ieee802154_keys; decrypt_info->key_number++) {
1797 guint nkeys = set_key_func(packet, key, alt_key, &ieee802154_keys[decrypt_info->key_number]);
1798 if (nkeys >= 1) {
1799 /* Try with the initial key */
1800 decrypt_info->key = key;
1801 payload_tvb = decrypt_func(tvb, offset, pinfo, packet, decrypt_info);
1802 if (!((*decrypt_info->status == DECRYPT_PACKET_MIC_CHECK_FAILED) || (*decrypt_info->status == DECRYPT_PACKET_DECRYPT_FAILED))) {
1803 break;
1804 }
1805 }
1806 if (nkeys >= 2) {
1807 /* Try also with the alternate key */
1808 decrypt_info->key = alt_key;
1809 payload_tvb = decrypt_func(tvb, offset, pinfo, packet, decrypt_info);
1810 if (!((*decrypt_info->status == DECRYPT_PACKET_MIC_CHECK_FAILED) || (*decrypt_info->status == DECRYPT_PACKET_DECRYPT_FAILED))) {
1811 break;
1812 }
1813 }
1814 }
1815 if (decrypt_info->key_number == num_ieee802154_keys) {
1816 /* None of the stored keys seemed to work */
1817 *decrypt_info->status = DECRYPT_PACKET_NO_KEY;
1818 }
1819
1820 /* Store the key number used for retrieval */
1821 ti = proto_tree_add_uint(key_tree, hf_ieee802154_key_number, tvb, 0, 0, decrypt_info->key_number);
1822 proto_item_set_hidden(ti);
1823 return payload_tvb;
1824 }
1825
1826
1827 /**
1828 * Check if the CRC-OK flag in the CC24xx metadata trailer is true
1829 * @param tvb the IEEE 802.15.4 frame
1830 * @return if the flag is true
1831 */
1832 static gboolean
is_cc24xx_crc_ok(tvbuff_t * tvb)1833 is_cc24xx_crc_ok(tvbuff_t *tvb)
1834 {
1835 return tvb_get_letohs(tvb, tvb_reported_length(tvb)-2) & IEEE802154_CC24xx_CRC_OK ? TRUE : FALSE;
1836 }
1837
1838 /**
1839 * Verify the 16/32 bit IEEE 802.15.4 FCS
1840 * @param tvb the IEEE 802.15.4 frame from the FCF up to and including the FCS
1841 * @return if the computed FCS matches the transmitted FCS
1842 */
1843 static gboolean
is_fcs_ok(tvbuff_t * tvb,guint fcs_len)1844 is_fcs_ok(tvbuff_t *tvb, guint fcs_len)
1845 {
1846 if (fcs_len == 2) {
1847 /* The FCS is in the last two bytes of the packet. */
1848 guint16 fcs = tvb_get_letohs(tvb, tvb_reported_length(tvb)-2);
1849 guint16 fcs_calc = (guint16) ieee802154_crc_tvb(tvb, tvb_reported_length(tvb)-2);
1850 return fcs == fcs_calc;
1851 }
1852 else {
1853 /* The FCS is in the last four bytes of the packet. */
1854 guint32 fcs = tvb_get_letohl(tvb, tvb_reported_length(tvb)-4);
1855 guint32 fcs_calc = ieee802154_crc32_tvb(tvb, tvb_reported_length(tvb)-4);
1856 return fcs == fcs_calc;
1857 }
1858 }
1859
1860 /**
1861 * Dissector for IEEE 802.15.4 packets with a PHY for which there's a
1862 * 4-octet preamble, a 1-octet SFD, and a 1-octet PHY header
1863 * with the uppermost bit reserved and the remaining 7 bits being
1864 * the frame length, and a 16-bit CRC value at the end.
1865 *
1866 * Currently, those are the following PHYs:
1867 *
1868 * O-QPSK
1869 * Binary phase-shift keying (BPSK)
1870 * GFSK
1871 * MSK
1872 * RCC DSSS BPSK
1873 *
1874 * @param tvb pointer to buffer containing raw packet.
1875 * @param pinfo pointer to packet information fields
1876 * @param tree pointer to data tree wireshark uses to display packet.
1877 */
1878 static int
dissect_ieee802154_nonask_phy(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)1879 dissect_ieee802154_nonask_phy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1880 {
1881 proto_tree *ieee802154_tree = NULL;
1882 proto_item *proto_root = NULL;
1883
1884 guint offset = 0;
1885 guint8 phr;
1886 tvbuff_t* mac;
1887
1888 /* Create the protocol tree. */
1889 if (tree) {
1890 proto_root = proto_tree_add_protocol_format(tree, proto_ieee802154_nonask_phy, tvb, 0, tvb_captured_length(tvb), "IEEE 802.15.4 non-ASK PHY");
1891 ieee802154_tree = proto_item_add_subtree(proto_root, ett_ieee802154_nonask_phy);
1892 }
1893
1894 /* Add the protocol name. */
1895 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IEEE 802.15.4 non-ASK PHY");
1896
1897 phr = tvb_get_guint8(tvb,offset+4+1);
1898
1899 if (tree) {
1900 guint loffset = offset;
1901 static int * const phr_fields[] = {
1902 &hf_ieee802154_nonask_phy_length,
1903 NULL
1904 };
1905
1906 proto_tree_add_item(ieee802154_tree, hf_ieee802154_nonask_phy_preamble, tvb, loffset, 4, ENC_LITTLE_ENDIAN);
1907 loffset +=4 ;
1908 proto_tree_add_item(ieee802154_tree, hf_ieee802154_nonask_phy_sfd, tvb, loffset, 1, ENC_LITTLE_ENDIAN);
1909 loffset +=1 ;
1910
1911 proto_tree_add_bitmask(ieee802154_tree, tvb, loffset, hf_ieee802154_nonask_phr, ett_ieee802154_nonask_phy_phr,
1912 phr_fields, ENC_NA);
1913 }
1914
1915 offset += 4+2*1;
1916 mac = tvb_new_subset_length_caplen(tvb,offset,-1, phr & IEEE802154_PHY_LENGTH_MASK);
1917
1918 /* These always have the FCS at the end. */
1919
1920 /*
1921 * Call the common dissector; FCS length is 2, and no flags.
1922 */
1923 dissect_ieee802154_common(mac, pinfo, ieee802154_tree, 2, 0);
1924 return tvb_captured_length(tvb);
1925 } /* dissect_ieee802154_nonask_phy */
1926
1927 /* Return the length in octets for the user configured
1928 * FCS/metadata following the PHY Payload */
1929 static guint
ieee802154_fcs_type_len(guint i)1930 ieee802154_fcs_type_len(guint i)
1931 {
1932 guint fcs_type_lengths[] = { 2, 2, 4 };
1933 if (i < array_length(fcs_type_lengths)) {
1934 return fcs_type_lengths[i];
1935 }
1936 return 0;
1937 }
1938
1939 /**
1940 * Dissector for IEEE 802.15.4 packet with an FCS containing a 16/32-bit
1941 * CRC value, or TI CC24xx metadata, at the end.
1942 *
1943 * @param tvb pointer to buffer containing raw packet.
1944 * @param pinfo pointer to packet information fields.
1945 * @param tree pointer to data tree wireshark uses to display packet.
1946 */
1947 static int
dissect_ieee802154(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)1948 dissect_ieee802154(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1949 {
1950 tvbuff_t *new_tvb = dissect_zboss_specific(tvb, pinfo, tree);
1951 guint options = 0;
1952 guint fcs_len;
1953
1954 /* Set the default FCS length based on the FCS type in the configuration */
1955 fcs_len = ieee802154_fcs_type_len(ieee802154_fcs_type);
1956
1957 if (ieee802154_fcs_type == IEEE802154_CC24XX_METADATA) {
1958 options = DISSECT_IEEE802154_OPTION_CC24xx;
1959 }
1960
1961 if (new_tvb != tvb) {
1962 /* ZBOSS traffic dump: always TI metadata trailer, always ZigBee */
1963 options = DISSECT_IEEE802154_OPTION_CC24xx|DISSECT_IEEE802154_OPTION_ZBOSS;
1964 fcs_len = 2;
1965 }
1966
1967 /* Call the common dissector. */
1968 dissect_ieee802154_common(new_tvb, pinfo, tree, fcs_len, options);
1969 return tvb_captured_length(tvb);
1970 } /* dissect_ieee802154 */
1971
1972 /**
1973 * Dissector for IEEE 802.15.4 packet with no FCS present.
1974 *
1975 * @param tvb pointer to buffer containing raw packet.
1976 * @param pinfo pointer to packet information fields
1977 * @param tree pointer to data tree wireshark uses to display packet.
1978 * @return captured length.
1979 */
1980 static int
dissect_ieee802154_nofcs(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)1981 dissect_ieee802154_nofcs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void * data _U_)
1982 {
1983 /*
1984 * Call the common dissector; FCS length is 0, and no flags.
1985 */
1986 dissect_ieee802154_common(tvb, pinfo, tree, 0, 0);
1987 return tvb_captured_length(tvb);
1988 } /* dissect_ieee802154_nofcs */
1989
1990 /**
1991 * Dissector for IEEE 802.15.4 packet dump produced by ZBOSS
1992 *
1993 * @param tvb pointer to buffer containing raw packet.
1994 * @param pinfo pointer to packet information fields
1995 * @param tree pointer to data tree wireshark uses to display packet.
1996 * @return new tvb subset if this is really ZBOSS dump, else oririnal tvb.
1997 */
1998 static tvbuff_t *
dissect_zboss_specific(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree)1999 dissect_zboss_specific(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
2000 {
2001 proto_tree *zboss_tree;
2002 proto_item *proto_root;
2003 guint off = 0;
2004 guint32 direction_byte, page_byte, channel;
2005
2006 if (tvb_captured_length(tvb) > 5)
2007 {
2008 if (tvb_get_guint8(tvb, off++) == 'Z'
2009 && tvb_get_guint8(tvb, off++) == 'B'
2010 && tvb_get_guint8(tvb, off++) == 'O'
2011 && tvb_get_guint8(tvb, off++) == 'S'
2012 && tvb_get_guint8(tvb, off++) == 'S')
2013 {
2014 /* Create the protocol tree. */
2015 proto_root = proto_tree_add_protocol_format(tree, proto_zboss, tvb, 0, tvb_captured_length(tvb), "ZBOSS dump");
2016 zboss_tree = proto_item_add_subtree(proto_root, ett_ieee802154_zboss);
2017
2018 proto_tree_add_item_ret_uint(zboss_tree, hf_zboss_direction, tvb, off, 1, ENC_NA, &direction_byte);
2019 proto_item_append_text(proto_root, ", %s", direction_byte ? "OUT" : "IN");
2020
2021 proto_tree_add_item_ret_uint(zboss_tree, hf_zboss_page, tvb, off, 1, ENC_NA, &page_byte);
2022 proto_item_append_text(proto_root, ", page %u", page_byte);
2023 off++;
2024
2025 proto_tree_add_item_ret_uint(zboss_tree, hf_zboss_channel, tvb, off, 1, ENC_NA, &channel);
2026 proto_item_append_text(proto_root, ", channel %u", channel);
2027 off++;
2028
2029 proto_tree_add_item(zboss_tree, hf_zboss_trace_number, tvb, off, 4, ENC_LITTLE_ENDIAN);
2030 off += 4;
2031
2032 return tvb_new_subset_remaining(tvb, off);
2033 }
2034 }
2035 return tvb;
2036 } /* dissect_zboss_specific */
2037
2038 /**
2039 * Dissector for IEEE 802.15.4 packet with 2 bytes of ChipCon/Texas
2040 * Instruments compatible metadata at the end of the frame, and no FCS.
2041 * This is typically called by layers encapsulating an IEEE 802.15.4 packet.
2042 *
2043 * @param tvb pointer to buffer containing raw packet.
2044 * @param pinfo pointer to packet information fields
2045 * @param tree pointer to data tree wireshark uses to display packet.
2046 */
2047 static int
dissect_ieee802154_cc24xx(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2048 dissect_ieee802154_cc24xx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void * data _U_)
2049 {
2050 /*
2051 * Call the common dissector.
2052 * 2 bytes of metadata at the end of the packet data.
2053 */
2054 dissect_ieee802154_common(tvb, pinfo, tree, 2, DISSECT_IEEE802154_OPTION_CC24xx);
2055 return tvb_captured_length(tvb);
2056 } /* dissect_ieee802154_cc24xx */
2057
2058 /**
2059 * Dissector for IEEE 802.15.4 TAP packet
2060 *
2061 * Contains optional TLVs and encapsulates an IEEE 802.15.4 packet.
2062 *
2063 * @param tvb pointer to buffer containing raw packet.
2064 * @param pinfo pointer to packet information fields
2065 * @param tree pointer to data tree wireshark uses to display packet.
2066 */
2067 static int
dissect_ieee802154_tap(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2068 dissect_ieee802154_tap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void * data _U_)
2069 {
2070 proto_tree *info_tree = NULL;
2071 proto_tree *header_tree = NULL;
2072 proto_item *proto_root = NULL;
2073 proto_item *ti = NULL;
2074 guint32 version = 0;
2075 guint32 length = 0;
2076 guint32 data_length = 0;
2077 tvbuff_t* tlv_tvb;
2078 tvbuff_t* payload_tvb;
2079 ieee802154_fcs_type_t tap_fcs_type;
2080 guint fcs_len;
2081
2082 /* Check the version in the TAP header */
2083 version = tvb_get_guint8(tvb, 0);
2084 if (version != 0) {
2085 /* Malformed packet. We do not understand any other version at this time */
2086 return 0;
2087 }
2088
2089 /* Get the total length of the header and TLVs */
2090 length = tvb_get_letohs(tvb, 2);
2091
2092 if (length > tvb_captured_length(tvb)) {
2093 /* Malformed packet. The TLVs exceeds our captured packet. */
2094 return 0;
2095 }
2096
2097 /* Create the protocol tree */
2098 proto_root = proto_tree_add_protocol_format(tree, proto_ieee802154_tap, tvb, 0, length, "IEEE 802.15.4 TAP");
2099 info_tree = proto_item_add_subtree(proto_root, ett_ieee802154_tap);
2100
2101 header_tree = proto_tree_add_subtree(info_tree, tvb, 0, 4, ett_ieee802154_tap_header, &proto_root, "Header");
2102 proto_tree_add_item(header_tree, hf_ieee802154_tap_version, tvb, 0, 1, ENC_LITTLE_ENDIAN);
2103 proto_tree_add_item(header_tree, hf_ieee802154_tap_reserved, tvb, 1, 1, ENC_LITTLE_ENDIAN);
2104 proto_tree_add_item(header_tree, hf_ieee802154_tap_length, tvb, 2, 2, ENC_LITTLE_ENDIAN);
2105
2106 /* Add the protocol name. */
2107 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IEEE 802.15.4 TAP");
2108
2109 /* Create a new tvb subset with only the TLVs to dissect */
2110 tlv_tvb = tvb_new_subset_length(tvb, 4, length - 4);
2111 tap_fcs_type = dissect_ieee802154_tap_tlvs(tlv_tvb, pinfo, info_tree);
2112
2113 /* Set the FCS length based on the FCS type */
2114 switch (tap_fcs_type) {
2115
2116 case IEEE802154_FCS_TYPE_NONE:
2117 fcs_len = 0;
2118 break;
2119
2120 case IEEE802154_FCS_TYPE_16_BIT:
2121 fcs_len = 2;
2122 break;
2123
2124 case IEEE802154_FCS_TYPE_32_BIT:
2125 fcs_len = 4;
2126 break;
2127
2128 default:
2129 /* Not valid */
2130 return tvb_captured_length(tvb);
2131 }
2132
2133 /* Report the remaining bytes as the IEEE 802.15.4 Data Length */
2134 data_length = tvb_reported_length_remaining(tvb, length);
2135 ti = proto_tree_add_uint(info_tree, hf_ieee802154_tap_data_length, NULL, 0, 0, data_length);
2136 proto_item_set_generated(ti);
2137
2138 /*
2139 * Call the common dissector with the real 802.15.4 data which follows the TLV header.
2140 * Create a separate packet bytes pane for the real data.
2141 * Specified FCS length, no flags.
2142 */
2143 payload_tvb = tvb_new_child_real_data(tvb, tvb_get_ptr(tvb, length, data_length), data_length, data_length);
2144 add_new_data_source(pinfo, payload_tvb, "IEEE 802.15.4 Data");
2145 dissect_ieee802154_common(payload_tvb, pinfo, tree, fcs_len, 0);
2146
2147 return tvb_captured_length(tvb);
2148 } /* dissect_ieee802154_tap */
2149
2150 /**
2151 * IEEE 802.15.4 packet dissection routine for Wireshark.
2152 *
2153 * This function extracts all the information first before displaying.
2154 * If payload exists, that portion will be passed into another dissector
2155 * for further processing.
2156 *
2157 * This is called after the individual dissect_ieee802154* functions
2158 * have been called to determine what sort of FCS is present, if any.
2159 *
2160 * @param tvb pointer to buffer containing raw packet.
2161 * @param pinfo pointer to packet information fields
2162 * @param tree pointer to data tree Wireshark uses to display packet.
2163 * @param options bitwise or of dissector options (see DISSECT_IEEE802154_OPTION_xxx).
2164 */
2165 static void
dissect_ieee802154_common(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint fcs_len,guint options)2166 dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint fcs_len, guint options)
2167 {
2168 proto_tree *ieee802154_tree;
2169 ieee802154_packet *packet;
2170 gboolean fcs_present;
2171 gboolean fcs_ok;
2172 tvbuff_t* no_fcs_tvb;
2173
2174 if (fcs_len != 0) {
2175 /*
2176 * Well, this packet should, in theory, have an FCS or CC24xx
2177 * metadata.
2178 * Do we have the entire packet, and does it have enough data for
2179 * the FCS/metadata?
2180 */
2181 guint reported_len = tvb_reported_length(tvb);
2182
2183 if (reported_len < fcs_len) {
2184 /*
2185 * The packet is claimed not to even have enough data
2186 * for the FCS/metadata. Pretend it doesn't have one.
2187 */
2188 no_fcs_tvb = tvb;
2189 fcs_present = FALSE;
2190 fcs_ok = TRUE; // assume OK if not present
2191 } else {
2192 /*
2193 * The packet is claimed to have enough data for the
2194 * FCS/metadata.
2195 * Slice it off from the reported length.
2196 */
2197 reported_len -= fcs_len;
2198 no_fcs_tvb = tvb_new_subset_length(tvb, 0, reported_len);
2199
2200 /*
2201 * Is the FCS/metadata present in the captured data?
2202 * reported_len is now the length of the packet without the
2203 * FCS/metadata, so the FCS/metadata begins at an offset of
2204 * reported_len.
2205 */
2206 if (tvb_bytes_exist(tvb, reported_len, fcs_len)) {
2207 /*
2208 * Yes. Check whether the FCS was OK.
2209 *
2210 * If we have an FCS, check it.
2211 * If we have metadata, check its "FCS OK" flag.
2212 */
2213 fcs_present = TRUE;
2214 fcs_ok = options & DISSECT_IEEE802154_OPTION_CC24xx ? is_cc24xx_crc_ok(tvb) : is_fcs_ok(tvb, fcs_len);
2215 } else {
2216 /*
2217 * No.
2218 *
2219 * Either 1) this means that there was a snapshot length
2220 * in effect when the capture was done, and that sliced
2221 * some or all of the FCS/metadata off or 2) this is a
2222 * capture with no FCS/metadata, using the same link-layer
2223 * header type value as captures with the FCS/metadata,
2224 * and indicating the lack of the FCS/metadata by having
2225 * the captured length be the length of the packet minus
2226 * the length of the FCS/metadata and the actual length
2227 * being the length of the packet including the FCS/metadata,
2228 * rather than by using the "no FCS" link-layer header type.
2229 *
2230 * We could try to distinguish between them by checking
2231 * for a captured length that's exactly fcs_len bytes
2232 * less than the actual length. That would allow us to
2233 * report packets that are cut short just before, or in
2234 * the middle of, the FCS as having been cut short by the
2235 * snapshot length.
2236 *
2237 * However, we can't distinguish between a packet that
2238 * happened to be cut fcs_len bytes short due to a
2239 * snapshot length being in effect when the capture was
2240 * done and a packet that *wasn't* cut short by a snapshot
2241 * length but that doesn't include the FCS/metadata.
2242 * Let's hope that rarely happens.
2243 */
2244 fcs_present = FALSE;
2245 fcs_ok = TRUE; // assume OK if not present
2246 }
2247 }
2248 } else {
2249 no_fcs_tvb = tvb;
2250 fcs_present = FALSE;
2251 fcs_ok = TRUE; // assume OK if not present
2252 }
2253
2254 guint mhr_len = ieee802154_dissect_header(no_fcs_tvb, pinfo, tree, 0, &ieee802154_tree, &packet);
2255 if (!mhr_len || tvb_reported_length_remaining(no_fcs_tvb, mhr_len) < 0 ) {
2256 return;
2257 }
2258
2259 if ((packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE) && (packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE)) {
2260 _find_or_create_conversation(pinfo, &pinfo->dl_src, &pinfo->dl_dst);
2261 }
2262
2263 if (ieee802154_ack_tracking && (packet->ack_request || packet->frame_type == IEEE802154_FCF_ACK)) {
2264 guint32 key[2] = {0};
2265
2266 key[0] = packet->seqno;
2267 if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID) {
2268 key[1] = pinfo->rec->rec_header.packet_header.interface_id;
2269 }
2270
2271 if (packet->ack_request) {
2272 transaction_start(pinfo, ieee802154_tree, packet, key);
2273 }
2274 else {
2275 transaction_end(pinfo, ieee802154_tree, packet, key);
2276 }
2277 }
2278
2279 tvbuff_t* payload = ieee802154_decrypt_payload(no_fcs_tvb, mhr_len, pinfo, ieee802154_tree, packet);
2280 if (payload) {
2281 guint pie_size = ieee802154_dissect_payload_ies(payload, pinfo, ieee802154_tree, packet);
2282 payload = tvb_new_subset_remaining(payload, pie_size);
2283 if (options & DISSECT_IEEE802154_OPTION_ZBOSS && packet->frame_type == IEEE802154_FCF_DATA) {
2284 if ((!fcs_ok && ieee802154_fcs_ok) || !tvb_reported_length(payload)) {
2285 call_data_dissector(payload, pinfo, tree);
2286 } else {
2287 call_dissector_with_data(zigbee_nwk_handle, payload, pinfo, tree, packet);
2288 }
2289 } else {
2290 ieee802154_dissect_frame_payload(payload, pinfo, ieee802154_tree, packet, fcs_ok);
2291 }
2292 }
2293
2294 if (fcs_present) {
2295 if (options & DISSECT_IEEE802154_OPTION_CC24xx)
2296 ieee802154_dissect_cc24xx_metadata(tvb, ieee802154_tree, fcs_ok);
2297 else
2298 ieee802154_dissect_fcs(tvb, ieee802154_tree, fcs_len, fcs_ok);
2299
2300 /* If the CRC is invalid, make a note of it in the info column. */
2301 if (!fcs_ok) {
2302 col_append_str(pinfo->cinfo, COL_INFO, ", Bad FCS");
2303 proto_item_append_text(proto_tree_get_parent(ieee802154_tree), ", Bad FCS");
2304
2305 /* Flag packet as having a bad crc. */
2306 expert_add_info(pinfo, proto_tree_get_parent(ieee802154_tree), &ei_ieee802154_fcs);
2307 }
2308 } else {
2309 if (ieee802154_tree) {
2310 /* Even if the FCS isn't present, add the fcs_ok field to the tree to
2311 * help with filter. Be sure not to make it visible though.
2312 */
2313 proto_item *ti = proto_tree_add_boolean_format_value(ieee802154_tree, hf_ieee802154_fcs_ok, tvb, 0, 0, fcs_ok, "Unknown");
2314 proto_item_set_hidden(ti);
2315 }
2316 }
2317
2318 tap_queue_packet(ieee802154_tap, pinfo, NULL);
2319 }
2320
2321 guint
ieee802154_dissect_header(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint options,proto_tree ** created_header_tree,ieee802154_packet ** parsed_info)2322 ieee802154_dissect_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint options, proto_tree **created_header_tree, ieee802154_packet **parsed_info)
2323 {
2324 proto_tree *ieee802154_tree = NULL;
2325 proto_item *proto_root = NULL;
2326 proto_item *hidden_item;
2327 proto_item *ti;
2328 guint offset = 0;
2329 ieee802154_packet *packet = wmem_new0(pinfo->pool, ieee802154_packet);
2330 ieee802154_short_addr addr16;
2331 ieee802154_hints_t *ieee_hints;
2332
2333 packet->short_table = ieee802154_map.short_table;
2334
2335 /* Allocate frame data with hints for upper layers */
2336 if (!PINFO_FD_VISITED(pinfo) ||
2337 (ieee_hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ieee802154, 0)) == NULL) {
2338 ieee_hints = wmem_new0(wmem_file_scope(), ieee802154_hints_t);
2339 p_add_proto_data(wmem_file_scope(), pinfo, proto_ieee802154, 0, ieee_hints);
2340 }
2341
2342 /* Save a pointer to the whole packet */
2343 ieee_hints->packet = packet;
2344
2345 /* Create the protocol tree. */
2346 if (tree) {
2347 proto_root = proto_tree_add_protocol_format(tree, proto_ieee802154, tvb, 0, tvb_captured_length(tvb), "IEEE 802.15.4");
2348 ieee802154_tree = proto_item_add_subtree(proto_root, ett_ieee802154);
2349 }
2350 /* Add the protocol name. */
2351 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IEEE 802.15.4");
2352
2353 /* Set out parameters */
2354 *created_header_tree = ieee802154_tree;
2355 *parsed_info = packet;
2356
2357 /* Add the packet length to the filter field */
2358 hidden_item = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_frame_length, NULL, 0, 0, tvb_reported_length(tvb));
2359 proto_item_set_hidden(hidden_item);
2360
2361 /* Frame Control Field */
2362 dissect_ieee802154_fcf(tvb, pinfo, ieee802154_tree, packet, &offset);
2363
2364 /* Sequence Number */
2365 if (packet->seqno_suppression) {
2366 if (packet->version != IEEE802154_VERSION_2015 && packet->frame_type != IEEE802154_FCF_MULTIPURPOSE) {
2367 expert_add_info(pinfo, proto_root, &ei_ieee802154_seqno_suppression);
2368 }
2369 } else { /* IEEE 802.15.4 Sequence Number Suppression */
2370 packet->seqno = tvb_get_guint8(tvb, offset);
2371 if (tree) {
2372 proto_tree_add_uint(ieee802154_tree, hf_ieee802154_seqno, tvb, offset, 1, packet->seqno);
2373 /* For Ack packets display this in the root. */
2374 if (packet->frame_type == IEEE802154_FCF_ACK) {
2375 proto_item_append_text(proto_root, ", Sequence Number: %u", packet->seqno);
2376 }
2377 }
2378 offset += 1;
2379 }
2380
2381 /*
2382 * ADDRESSING FIELDS
2383 */
2384 /* Clear out the addressing strings. */
2385 clear_address(&pinfo->net_dst);
2386 clear_address(&pinfo->dl_dst);
2387 clear_address(&pinfo->dst);
2388 clear_address(&pinfo->net_src);
2389 clear_address(&pinfo->dl_src);
2390 clear_address(&pinfo->src);
2391
2392 if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_RESERVED) {
2393 /* Invalid Destination Address Mode. Abort Dissection. */
2394 expert_add_info(pinfo, proto_root, &ei_ieee802154_dst);
2395 return 0;
2396 }
2397
2398 if (packet->src_addr_mode == IEEE802154_FCF_ADDR_RESERVED) {
2399 /* Invalid Source Address Mode. Abort Dissection. */
2400 expert_add_info(pinfo, proto_root, &ei_ieee802154_src);
2401 return 0;
2402 }
2403
2404 if (packet->frame_type == IEEE802154_FCF_MULTIPURPOSE) {
2405 /* Multipurpose frames have a different set of frame versions, with 0 as the only valid version */
2406 if (packet->version != 0) {
2407 /* Unknown Frame Version for Multipurpose frames. Abort Dissection */
2408 expert_add_info(pinfo, proto_root, &ei_ieee802154_frame_ver);
2409 return 0;
2410 }
2411
2412 /* The source PAN ID is always omitted in multipurpose frames */
2413 packet->src_pan_present = FALSE;
2414
2415 if (packet->pan_id_present) {
2416 packet->dst_pan_present = TRUE;
2417 }
2418 }
2419 else if (packet->version == IEEE802154_VERSION_RESERVED) {
2420 /* Unknown Frame Version. Abort Dissection. */
2421 expert_add_info(pinfo, proto_root, &ei_ieee802154_frame_ver);
2422 return 0;
2423 }
2424 else if ((packet->version == IEEE802154_VERSION_2003) || /* For Frame Version 0b00 and */
2425 (packet->version == IEEE802154_VERSION_2006)) { /* 0b01 effect defined in section 7.2.1.5 */
2426
2427 if ((packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE) && /* if both destination and source */
2428 (packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE)) { /* addressing information is present */
2429 if (packet->pan_id_compression == 1) { /* PAN IDs are identical */
2430 packet->dst_pan_present = TRUE;
2431 packet->src_pan_present = FALSE; /* source PAN ID is omitted */
2432 }
2433 else { /* PAN IDs are different, both shall be included in the frame */
2434 packet->dst_pan_present = TRUE;
2435 packet->src_pan_present = TRUE;
2436 }
2437 }
2438 else {
2439 if (packet->pan_id_compression == 1) { /* all remaining cases pan_id_compression must be zero */
2440 expert_add_info(pinfo, proto_root, &ei_ieee802154_invalid_panid_compression);
2441 return 0;
2442 }
2443 else {
2444 /* only either the destination or the source addressing information is present */
2445 if ((packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE) && /* Present */
2446 (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE)) { /* Not Present */
2447 packet->dst_pan_present = TRUE;
2448 packet->src_pan_present = FALSE;
2449 }
2450 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
2451 (packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE)) { /* Present */
2452 packet->dst_pan_present = FALSE;
2453 packet->src_pan_present = TRUE;
2454 }
2455 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
2456 (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE)) { /* Not Present */
2457 packet->dst_pan_present = FALSE;
2458 packet->src_pan_present = FALSE;
2459 }
2460 else {
2461 expert_add_info(pinfo, proto_root, &ei_ieee802154_invalid_addressing);
2462 return 0;
2463 }
2464 }
2465 }
2466 }
2467 else if (packet->version == IEEE802154_VERSION_2015) {
2468 /* for Frame Version 0b10 PAN Id Compression only applies to these frame types */
2469 if ((packet->frame_type == IEEE802154_FCF_BEACON) ||
2470 (packet->frame_type == IEEE802154_FCF_DATA) ||
2471 (packet->frame_type == IEEE802154_FCF_ACK) ||
2472 (packet->frame_type == IEEE802154_FCF_CMD) ) {
2473
2474 /* Implements Table 7-6 of IEEE 802.15.4-2015
2475 *
2476 * Destination Address Source Address Destination PAN ID Source PAN ID PAN ID Compression
2477 *-------------------------------------------------------------------------------------------------
2478 * 1. Not Present Not Present Not Present Not Present 0
2479 * 2. Not Present Not Present Present Not Present 1
2480 * 3. Present Not Present Present Not Present 0
2481 * 4. Present Not Present Not Present Not Present 1
2482 *
2483 * 5. Not Present Present Not Present Present 0
2484 * 6. Not Present Present Not Present Not Present 1
2485 *
2486 * 7. Extended Extended Present Not Present 0
2487 * 8. Extended Extended Not Present Not Present 1
2488 *
2489 * 9. Short Short Present Present 0
2490 * 10. Short Extended Present Present 0
2491 * 11. Extended Short Present Present 0
2492 *
2493 * 12. Short Extended Present Not Present 1
2494 * 13. Extended Short Present Not Present 1
2495 * 14. Short Short Present Not Present 1
2496 */
2497
2498 /* Row 1 */
2499 if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
2500 (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
2501 (packet->pan_id_compression == 0)) {
2502 packet->dst_pan_present = FALSE;
2503 packet->src_pan_present = FALSE;
2504 }
2505 /* Row 2 */
2506 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
2507 (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
2508 (packet->pan_id_compression == 1)) {
2509 packet->dst_pan_present = TRUE;
2510 packet->src_pan_present = FALSE;
2511 }
2512 /* Row 3 */
2513 else if ((packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE) && /* Present */
2514 (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
2515 (packet->pan_id_compression == 0)) {
2516 packet->dst_pan_present = TRUE;
2517 packet->src_pan_present = FALSE;
2518 }
2519 /* Row 4 */
2520 else if ((packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE) && /* Present */
2521 (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
2522 (packet->pan_id_compression == 1)) {
2523 packet->dst_pan_present = FALSE;
2524 packet->src_pan_present = FALSE;
2525 }
2526 /* Row 5 */
2527 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
2528 (packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE) && /* Present */
2529 (packet->pan_id_compression == 0)) {
2530 packet->dst_pan_present = FALSE;
2531 packet->src_pan_present = TRUE;
2532 }
2533 /* Row 6 */
2534 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
2535 (packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE) && /* Present */
2536 (packet->pan_id_compression == 1)) {
2537 packet->dst_pan_present = FALSE;
2538 packet->src_pan_present = FALSE;
2539 }
2540 /* Row 7 */
2541 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) && /* Extended */
2542 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) && /* Extended */
2543 (packet->pan_id_compression == 0)) {
2544 packet->dst_pan_present = TRUE;
2545 packet->src_pan_present = FALSE;
2546 }
2547 /* Row 8 */
2548 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) && /* Extended */
2549 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) && /* Extended */
2550 (packet->pan_id_compression == 1)) {
2551 packet->dst_pan_present = FALSE;
2552 packet->src_pan_present = FALSE;
2553 }
2554 /* Row 9 */
2555 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) && /* Short */
2556 (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) && /* Short */
2557 (packet->pan_id_compression == 0)) {
2558 packet->dst_pan_present = TRUE;
2559 packet->src_pan_present = (ieee802154e_compatibility ? FALSE : TRUE);
2560 }
2561 /* Row 10 */
2562 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) && /* Short */
2563 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) && /* Extended */
2564 (packet->pan_id_compression == 0)) {
2565 packet->dst_pan_present = TRUE;
2566 packet->src_pan_present = (ieee802154e_compatibility ? FALSE : TRUE);
2567 }
2568 /* Row 11 */
2569 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) && /* Extended */
2570 (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) && /* Short */
2571 (packet->pan_id_compression == 0)) {
2572 packet->dst_pan_present = TRUE;
2573 packet->src_pan_present = (ieee802154e_compatibility ? FALSE : TRUE);
2574 }
2575 /* Row 12 */
2576 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) && /* Short */
2577 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) && /* Extended */
2578 (packet->pan_id_compression == 1)) {
2579 packet->dst_pan_present = TRUE;
2580 packet->src_pan_present = FALSE;
2581 }
2582 /* Row 13 */
2583 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) && /* Extended */
2584 (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) && /* Short */
2585 (packet->pan_id_compression == 1)) {
2586 packet->dst_pan_present = TRUE;
2587 packet->src_pan_present = FALSE;
2588 }
2589 /* Row 14 */
2590 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) && /* Short */
2591 (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) && /* Short */
2592 (packet->pan_id_compression == 1)) {
2593 packet->dst_pan_present = TRUE;
2594 packet->src_pan_present = FALSE;
2595 }
2596 else {
2597 expert_add_info(pinfo, proto_root, &ei_ieee802154_invalid_panid_compression2);
2598 return 0;
2599 }
2600 }
2601 else { /* Frame Type is neither Beacon, Data, Ack, nor Command: PAN ID Compression is not used */
2602 packet->dst_pan_present = FALSE; /* no PAN ID will */
2603 packet->src_pan_present = FALSE; /* be present */
2604 }
2605 }
2606 else {
2607 /* Unknown Frame Version. Abort Dissection. */
2608 expert_add_info(pinfo, proto_root, &ei_ieee802154_frame_ver);
2609 return 0;
2610 }
2611
2612 /*
2613 * Addressing Fields
2614 */
2615
2616 /* Destination PAN Id */
2617 if (packet->dst_pan_present) {
2618 packet->dst_pan = tvb_get_letohs(tvb, offset);
2619 if (ieee802154_tree) {
2620 proto_tree_add_uint(ieee802154_tree, hf_ieee802154_dst_panID, tvb, offset, 2, packet->dst_pan);
2621 }
2622 offset += 2;
2623 }
2624
2625 /* Destination Address */
2626 if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
2627 gchar* dst_addr;
2628
2629 /* Get the address. */
2630 packet->dst16 = tvb_get_letohs(tvb, offset);
2631
2632 /* Provide address hints to higher layers that need it. */
2633 if (ieee_hints) {
2634 ieee_hints->dst16 = packet->dst16;
2635 }
2636
2637 set_address_tvb(&pinfo->dl_dst, ieee802_15_4_short_address_type, 2, tvb, offset);
2638 copy_address_shallow(&pinfo->dst, &pinfo->dl_dst);
2639 dst_addr = address_to_str(pinfo->pool, &pinfo->dst);
2640
2641 proto_tree_add_uint(ieee802154_tree, hf_ieee802154_dst16, tvb, offset, 2, packet->dst16);
2642 proto_item_append_text(proto_root, ", Dst: %s", dst_addr);
2643 ti = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_addr16, tvb, offset, 2, packet->dst16);
2644 proto_item_set_generated(ti);
2645 proto_item_set_hidden(ti);
2646
2647 col_append_fstr(pinfo->cinfo, COL_INFO, ", Dst: %s", dst_addr);
2648 offset += 2;
2649 }
2650 else if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) {
2651 guint64 *p_addr = (guint64 *)wmem_new(pinfo->pool, guint64);
2652
2653 /* Get the address */
2654 packet->dst64 = tvb_get_letoh64(tvb, offset);
2655
2656 /* Copy and convert the address to network byte order. */
2657 *p_addr = pntoh64(&(packet->dst64));
2658
2659 /* Display the destination address. */
2660 /* XXX - OUI resolution doesn't happen when displaying resolved
2661 * EUI64 addresses; that should probably be fixed in
2662 * epan/addr_resolv.c.
2663 */
2664 set_address(&pinfo->dl_dst, AT_EUI64, 8, p_addr);
2665 copy_address_shallow(&pinfo->dst, &pinfo->dl_dst);
2666 if (tree) {
2667 proto_tree_add_item(ieee802154_tree, hf_ieee802154_dst64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2668 proto_item_append_text(proto_root, ", Dst: %s", eui64_to_display(pinfo->pool, packet->dst64));
2669 ti = proto_tree_add_item(ieee802154_tree, hf_ieee802154_addr64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2670 proto_item_set_generated(ti);
2671 proto_item_set_hidden(ti);
2672 }
2673 col_append_fstr(pinfo->cinfo, COL_INFO, ", Dst: %s", eui64_to_display(pinfo->pool, packet->dst64));
2674 offset += 8;
2675 }
2676
2677 /* Source PAN Id */
2678 if (packet->src_pan_present) {
2679 packet->src_pan = tvb_get_letohs(tvb, offset);
2680 proto_tree_add_uint(ieee802154_tree, hf_ieee802154_src_panID, tvb, offset, 2, packet->src_pan);
2681 offset += 2;
2682 }
2683 else {
2684 if (packet->dst_pan_present) {
2685 packet->src_pan = packet->dst_pan;
2686 }
2687 else {
2688 packet->src_pan = IEEE802154_BCAST_PAN;
2689 }
2690 }
2691 if (ieee_hints) {
2692 ieee_hints->src_pan = packet->src_pan;
2693 }
2694
2695 /* Source Address */
2696 if (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
2697 gchar* src_addr;
2698
2699 /* Get the address. */
2700 packet->src16 = tvb_get_letohs(tvb, offset);
2701
2702 if (!PINFO_FD_VISITED(pinfo)) {
2703 /* If we know our extended source address from previous packets,
2704 * provide a pointer to it in a hint for upper layers */
2705 addr16.addr = packet->src16;
2706 addr16.pan = packet->src_pan;
2707
2708 if (ieee_hints) {
2709 ieee_hints->src16 = packet->src16;
2710 ieee_hints->map_rec = (ieee802154_map_rec *)
2711 g_hash_table_lookup(ieee802154_map.short_table, &addr16);
2712 }
2713 }
2714
2715 set_address_tvb(&pinfo->dl_src, ieee802_15_4_short_address_type, 2, tvb, offset);
2716 copy_address_shallow(&pinfo->src, &pinfo->dl_src);
2717 src_addr = address_to_str(pinfo->pool, &pinfo->src);
2718
2719 /* Add the addressing info to the tree. */
2720 if (tree) {
2721 proto_tree_add_uint(ieee802154_tree, hf_ieee802154_src16, tvb, offset, 2, packet->src16);
2722 proto_item_append_text(proto_root, ", Src: %s", src_addr);
2723 ti = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_addr16, tvb, offset, 2, packet->src16);
2724 proto_item_set_generated(ti);
2725 proto_item_set_hidden(ti);
2726
2727 if (ieee_hints && ieee_hints->map_rec) {
2728 /* Display inferred source address info */
2729 ti = proto_tree_add_eui64(ieee802154_tree, hf_ieee802154_src64, tvb, offset, 0,
2730 ieee_hints->map_rec->addr64);
2731 proto_item_set_generated(ti);
2732 ti = proto_tree_add_eui64(ieee802154_tree, hf_ieee802154_addr64, tvb, offset, 0, ieee_hints->map_rec->addr64);
2733 proto_item_set_generated(ti);
2734 proto_item_set_hidden(ti);
2735
2736 if ( ieee_hints->map_rec->start_fnum ) {
2737 ti = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_src64_origin, tvb, 0, 0,
2738 ieee_hints->map_rec->start_fnum);
2739 }
2740 else {
2741 ti = proto_tree_add_uint_format_value(ieee802154_tree, hf_ieee802154_src64_origin, tvb, 0, 0,
2742 ieee_hints->map_rec->start_fnum, "Pre-configured");
2743 }
2744 proto_item_set_generated(ti);
2745 }
2746 }
2747
2748 col_append_fstr(pinfo->cinfo, COL_INFO, ", Src: %s", src_addr);
2749
2750 offset += 2;
2751 }
2752 else if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
2753 guint64 *p_addr = (guint64 *)wmem_new(pinfo->pool, guint64);
2754
2755 /* Get the address. */
2756 packet->src64 = tvb_get_letoh64(tvb, offset);
2757
2758 /* Copy and convert the address to network byte order. */
2759 *p_addr = pntoh64(&(packet->src64));
2760
2761 /* Display the source address. */
2762 /* XXX - OUI resolution doesn't happen when displaying resolved
2763 * EUI64 addresses; that should probably be fixed in
2764 * epan/addr_resolv.c.
2765 */
2766 set_address(&pinfo->dl_src, AT_EUI64, 8, p_addr);
2767 copy_address_shallow(&pinfo->src, &pinfo->dl_src);
2768 if (tree) {
2769 proto_tree_add_item(ieee802154_tree, hf_ieee802154_src64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2770 proto_item_append_text(proto_root, ", Src: %s", eui64_to_display(pinfo->pool, packet->src64));
2771 ti = proto_tree_add_item(ieee802154_tree, hf_ieee802154_addr64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2772 proto_item_set_generated(ti);
2773 proto_item_set_hidden(ti);
2774 }
2775
2776 col_append_fstr(pinfo->cinfo, COL_INFO, ", Src: %s", eui64_to_display(pinfo->pool, packet->src64));
2777 offset += 8;
2778 }
2779
2780 /* Existence of the Auxiliary Security Header is controlled by the Security Enabled Field */
2781 if ((packet->security_enable) && (packet->version != IEEE802154_VERSION_2003) && !(options & IEEE802154_DISSECT_HEADER_OPTION_NO_AUX_SEC_HDR)) {
2782 dissect_ieee802154_aux_sec_header_and_key(tvb, pinfo, ieee802154_tree, packet, &offset);
2783 }
2784
2785 /*
2786 * NONPAYLOAD FIELDS
2787 *
2788 */
2789 /* All of the beacon fields, except the beacon payload are considered nonpayload. */
2790 if (((packet->version == IEEE802154_VERSION_2003) || (packet->version == IEEE802154_VERSION_2006)) && (packet->frame_type != IEEE802154_FCF_MULTIPURPOSE)) {
2791 if (packet->frame_type == IEEE802154_FCF_BEACON) { /* Regular Beacon. Some are not present in frame version (Enhanced) Beacons */
2792 dissect_ieee802154_superframe(tvb, pinfo, ieee802154_tree, &offset); /* superframe spec */
2793 dissect_ieee802154_gtsinfo(tvb, pinfo, ieee802154_tree, &offset); /* GTS information fields */
2794 dissect_ieee802154_pendaddr(tvb, pinfo, ieee802154_tree, &offset); /* Pending address list */
2795 }
2796
2797 if (packet->frame_type == IEEE802154_FCF_CMD) {
2798 /**
2799 * In IEEE802.15.4-2003 and 2006 the command identifier is considered to be part of the header
2800 * and is thus not encrypted. For IEEE802.15.4-2012e and later the command id is considered to be
2801 * part of the payload, is encrypted, and follows the payload IEs. Thus we only parse the command id
2802 * here for 2006 and earlier frames. */
2803 packet->command_id = tvb_get_guint8(tvb, offset);
2804 if (tree) {
2805 proto_tree_add_uint(ieee802154_tree, hf_ieee802154_cmd_id, tvb, offset, 1, packet->command_id);
2806 }
2807 offset++;
2808
2809 /* Display the command identifier in the info column. */
2810 col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
2811 }
2812 }
2813 else {
2814 if (packet->ie_present) {
2815 offset += dissect_ieee802154_header_ie(tvb, pinfo, ieee802154_tree, offset, packet);
2816 }
2817 }
2818
2819 /* IEEE 802.15.4-2003 may have security information pre-pended to payload */
2820 if (packet->security_enable && (packet->version == IEEE802154_VERSION_2003)) {
2821 /* Store security suite preference in the 2006 security level identifier to simplify 2003 integration! */
2822 packet->security_level = (ieee802154_security_level)ieee802154_sec_suite;
2823
2824 /* Frame Counter and Key Sequence Counter prepended to the payload of an encrypted frame */
2825 if (IEEE802154_IS_ENCRYPTED(packet->security_level)) {
2826 packet->frame_counter = tvb_get_letohl (tvb, offset);
2827 proto_tree_add_uint(ieee802154_tree, hf_ieee802154_sec_frame_counter, tvb, offset, (int)sizeof(guint32), packet->frame_counter);
2828 offset += (int)sizeof(guint32);
2829
2830 packet->key_sequence_counter = tvb_get_guint8 (tvb, offset);
2831 proto_tree_add_uint(ieee802154_tree, hf_ieee802154_sec_key_sequence_counter, tvb, offset, (int)sizeof(guint8), packet->key_sequence_counter);
2832 offset += (int)sizeof(guint8);
2833 }
2834 }
2835
2836 return offset;
2837 }
2838
2839 /*
2840 * XXX - "mhr_len" is really a general offset; this is used elsewhere.
2841 */
2842 tvbuff_t*
ieee802154_decrypt_payload(tvbuff_t * tvb,guint mhr_len,packet_info * pinfo,proto_tree * ieee802154_tree,ieee802154_packet * packet)2843 ieee802154_decrypt_payload(tvbuff_t *tvb, guint mhr_len, packet_info *pinfo, proto_tree *ieee802154_tree, ieee802154_packet *packet)
2844 {
2845 proto_item *proto_root = proto_tree_get_parent(ieee802154_tree);
2846 proto_tree *tree = proto_tree_get_parent_tree(ieee802154_tree);
2847 unsigned char rx_mic[IEEE802154_CIPHER_SIZE];
2848 guint rx_mic_len = IEEE802154_MIC_LENGTH(packet->security_level);
2849 ieee802154_decrypt_status status = DECRYPT_NOT_ENCRYPTED;
2850 tvbuff_t *payload_tvb;
2851
2852 /* Encrypted Payload. */
2853 if (packet->security_enable) {
2854 ieee802154_decrypt_info_t decrypt_info;
2855
2856 decrypt_info.rx_mic = rx_mic;
2857 decrypt_info.rx_mic_length = &rx_mic_len;
2858 decrypt_info.status = &status;
2859 decrypt_info.key = NULL; /* payload function will fill that in */
2860
2861 /* call with NULL tree since we add the key_number below without hiding it */
2862 payload_tvb = decrypt_ieee802154_payload(tvb, mhr_len, pinfo, NULL, packet, &decrypt_info,
2863 ieee802154_set_mac_key, dissect_ieee802154_decrypt);
2864
2865 /* Get the unencrypted data if decryption failed. */
2866 if (!payload_tvb) {
2867 /* Deal with possible truncation and the MIC field at the end. */
2868 gint reported_len = tvb_reported_length(tvb)-mhr_len-rx_mic_len;
2869 payload_tvb = tvb_new_subset_length(tvb, mhr_len, reported_len);
2870 }
2871
2872 /* Display the MIC. */
2873 if (rx_mic_len) {
2874 if (tvb_bytes_exist(tvb, tvb_reported_length(tvb) - rx_mic_len, rx_mic_len)) {
2875 proto_tree_add_item(ieee802154_tree, hf_ieee802154_mic, tvb, tvb_reported_length(tvb)-rx_mic_len, rx_mic_len, ENC_NA);
2876 }
2877 }
2878
2879 /* Display the reason for failure, and abort if the error was fatal. */
2880 switch (status) {
2881 case DECRYPT_PACKET_SUCCEEDED:
2882 {
2883 proto_item *pi = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_key_number, tvb, 0, 0, decrypt_info.key_number);
2884 proto_item_set_generated(pi);
2885 break;
2886 }
2887 case DECRYPT_NOT_ENCRYPTED:
2888 break; // nothing to do
2889
2890 case DECRYPT_FRAME_COUNTER_SUPPRESSION_UNSUPPORTED:
2891 expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "Decryption of 802.15.4-2015 with frame counter suppression is not supported");
2892 call_data_dissector(payload_tvb, pinfo, tree);
2893 return NULL;
2894
2895 case DECRYPT_PACKET_TOO_SMALL:
2896 expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "Packet was too small to include the CRC and MIC");
2897 call_data_dissector(payload_tvb, pinfo, tree);
2898 return NULL;
2899
2900 case DECRYPT_PACKET_NO_EXT_SRC_ADDR:
2901 expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "No extended source address - can't decrypt");
2902 call_data_dissector(payload_tvb, pinfo, tree);
2903 return NULL;
2904
2905 case DECRYPT_PACKET_NO_KEY:
2906 expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "No encryption key set - can't decrypt");
2907 call_data_dissector(payload_tvb, pinfo, tree);
2908 return NULL;
2909
2910 case DECRYPT_PACKET_DECRYPT_FAILED:
2911 expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "Decrypt failed");
2912 call_data_dissector(payload_tvb, pinfo, tree);
2913 return NULL;
2914
2915 case DECRYPT_PACKET_MIC_CHECK_FAILED:
2916 expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "MIC check failed");
2917 /*
2918 * Abort only if the payload was encrypted, in which case we
2919 * probably didn't decrypt the packet right (eg: wrong key).
2920 */
2921 if (IEEE802154_IS_ENCRYPTED(packet->security_level)) {
2922 call_data_dissector(payload_tvb, pinfo, tree);
2923 return NULL;
2924 }
2925 break;
2926 }
2927 }
2928 /* Plaintext Payload. */
2929 else {
2930 /* Deal with possible truncation. */
2931 gint reported_len = tvb_reported_length(tvb)-mhr_len;
2932 payload_tvb = tvb_new_subset_length(tvb, mhr_len, reported_len);
2933 }
2934
2935 return payload_tvb;
2936 }
2937
2938
ieee802154_dissect_payload_ies(tvbuff_t * tvb,packet_info * pinfo,proto_tree * ieee802154_tree,ieee802154_packet * packet)2939 guint ieee802154_dissect_payload_ies(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ieee802154_tree, ieee802154_packet *packet)
2940 {
2941 /* Presence of Payload IEs is defined by the termination of the Header IEs */
2942 if (packet->payload_ie_present) {
2943 if (tvb_reported_length(tvb) > 2) {
2944 return (guint) dissect_ieee802154_payload_ie(tvb, pinfo, ieee802154_tree, 0, packet);
2945 } else {
2946 expert_add_info(pinfo, proto_tree_get_parent(ieee802154_tree), &ei_ieee802154_missing_payload_ie);
2947 }
2948 }
2949 return 0;
2950 }
2951
2952
ieee802154_dissect_frame_payload(tvbuff_t * tvb,packet_info * pinfo,proto_tree * ieee802154_tree,ieee802154_packet * packet,gboolean fcs_ok)2953 guint ieee802154_dissect_frame_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ieee802154_tree, ieee802154_packet *packet, gboolean fcs_ok)
2954 {
2955 tvbuff_t *payload_tvb = tvb;
2956 proto_tree *tree = proto_tree_get_parent_tree(ieee802154_tree);
2957 heur_dtbl_entry_t *hdtbl_entry;
2958
2959 /* There are commands without payload */
2960 if (tvb_captured_length(payload_tvb) > 0 || packet->frame_type == IEEE802154_FCF_CMD) {
2961 /*
2962 * Wrap the sub-dissection in a try/catch block in case the payload is
2963 * broken. First we store the current protocol so we can fix it if an
2964 * exception is thrown by the subdissectors.
2965 */
2966 const char* saved_proto = pinfo->current_proto;
2967 /* Try to dissect the payload. */
2968 TRY {
2969 switch (packet->frame_type) {
2970 case IEEE802154_FCF_BEACON:
2971 if (!dissector_try_heuristic(ieee802154_beacon_subdissector_list, payload_tvb, pinfo, tree, &hdtbl_entry, packet)) {
2972 /* Could not subdissect, call the data dissector instead. */
2973 call_data_dissector(payload_tvb, pinfo, tree);
2974 }
2975 break;
2976
2977 case IEEE802154_FCF_CMD:
2978 dissect_ieee802154_command(payload_tvb, pinfo, ieee802154_tree, packet);
2979 break;
2980
2981 case IEEE802154_FCF_DATA:
2982 /* Sanity-check. */
2983 if ((!fcs_ok && ieee802154_fcs_ok) || !tvb_reported_length(payload_tvb)) {
2984 call_data_dissector(payload_tvb, pinfo, tree);
2985 break;
2986 }
2987 /* Try the PANID dissector table for stateful dissection. */
2988 if (dissector_try_uint_new(panid_dissector_table, packet->src_pan, payload_tvb, pinfo, tree, TRUE, packet)) {
2989 break;
2990 }
2991 /* Try again with the destination PANID (if different) */
2992 if (((packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) ||
2993 (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT)) &&
2994 (packet->dst_pan != packet->src_pan) &&
2995 dissector_try_uint_new(panid_dissector_table, packet->src_pan, payload_tvb, pinfo, tree, TRUE, packet)) {
2996 break;
2997 }
2998 /* Try heuristic dissection. */
2999 if (dissector_try_heuristic(ieee802154_heur_subdissector_list, payload_tvb, pinfo, tree, &hdtbl_entry, packet)) break;
3000 /* Fall-through to dump undissectable payloads. */
3001 /* FALL THROUGH */
3002 default:
3003 /* Could not subdissect, call the data dissector instead. */
3004 call_data_dissector(payload_tvb, pinfo, tree);
3005 } /* switch */
3006 }
3007 CATCH_ALL {
3008 /*
3009 * Someone encountered an error while dissecting the payload. But
3010 * we haven't yet finished processing all of our layer. Catch and
3011 * display the exception, then fall-through to finish displaying
3012 * the FCS (which we display last so the frame is ordered correctly
3013 * in the tree).
3014 */
3015 show_exception(payload_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
3016 pinfo->current_proto = saved_proto;
3017 }
3018 ENDTRY;
3019 }
3020 return tvb_captured_length(tvb);
3021 }
3022
3023 /**
3024 * Dissect the FCS at the end of the frame.
3025 * That is only displayed if the included length of the tvb encompasses it.
3026 *
3027 * @param tvb the 802.15.4 frame tvb
3028 * @param ieee802154_tree the 802.15.4 protocol tree
3029 * @param fcs_len length of the FCS field
3030 * @param fcs_ok set to FALSE to indicate FCS verification failed
3031 */
3032 static void
ieee802154_dissect_fcs(tvbuff_t * tvb,proto_tree * ieee802154_tree,guint fcs_len,gboolean fcs_ok)3033 ieee802154_dissect_fcs(tvbuff_t *tvb, proto_tree *ieee802154_tree, guint fcs_len, gboolean fcs_ok)
3034 {
3035 proto_item *ti;
3036 /* The FCS should be the last bytes of the reported packet. */
3037 guint offset = tvb_reported_length(tvb)-fcs_len;
3038 /* Dissect the FCS only if it exists (captures which don't or can't get the
3039 * FCS will simply truncate the packet to omit it, but should still set the
3040 * reported length to cover the original packet length), so if the snapshot
3041 * is too short for an FCS don't make a fuss.
3042 */
3043 if (ieee802154_tree) {
3044 if (fcs_len == 2) {
3045 guint16 fcs = tvb_get_letohs(tvb, offset);
3046
3047 ti = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_fcs, tvb, offset, 2, fcs);
3048 if (fcs_ok) {
3049 proto_item_append_text(ti, " (Correct)");
3050 }
3051 else {
3052 proto_item_append_text(ti, " (Incorrect, expected FCS=0x%04x)", ieee802154_crc_tvb(tvb, offset));
3053 }
3054 /* To Help with filtering, add the fcs_ok field to the tree. */
3055 ti = proto_tree_add_boolean(ieee802154_tree, hf_ieee802154_fcs_ok, tvb, offset, 2, (guint32) fcs_ok);
3056 proto_item_set_hidden(ti);
3057 }
3058 else {
3059 guint32 fcs = tvb_get_letohl(tvb, offset);
3060
3061 ti = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_fcs32, tvb, offset, 4, fcs);
3062 if (fcs_ok) {
3063 proto_item_append_text(ti, " (Correct)");
3064 }
3065 else {
3066 proto_item_append_text(ti, " (Incorrect, expected FCS=0x%08x)", ieee802154_crc32_tvb(tvb, offset));
3067 }
3068 /* To Help with filtering, add the fcs_ok field to the tree. */
3069 ti = proto_tree_add_boolean(ieee802154_tree, hf_ieee802154_fcs_ok, tvb, offset, 2, (guint32) fcs_ok);
3070 proto_item_set_hidden(ti);
3071 }
3072 }
3073 } /* ieee802154_dissect_fcs */
3074
3075 /**
3076 * Dissect the TI CC24xx metadata at the end of the frame.
3077 * That is only displayed if the included length of the tvb encompasses it.
3078 *
3079 * @param tvb the 802.15.4 frame tvb
3080 * @param ieee802154_tree the 802.15.4 protocol tree
3081 * @param fcs_ok set to FALSE to indicate FCS verification failed
3082 */
3083 static void
ieee802154_dissect_cc24xx_metadata(tvbuff_t * tvb,proto_tree * ieee802154_tree,gboolean fcs_ok)3084 ieee802154_dissect_cc24xx_metadata(tvbuff_t *tvb, proto_tree *ieee802154_tree, gboolean fcs_ok)
3085 {
3086 /* The metadata should be the last 2 bytes of the reported packet. */
3087 guint offset = tvb_reported_length(tvb)-2;
3088 /* Dissect the metadata only if it exists (captures which don't or can't get the
3089 * metadata will simply truncate the packet to omit it, but should still set the
3090 * reported length to cover the original packet length), so if the snapshot
3091 * is too short for the metadata don't make a fuss.
3092 */
3093 if (ieee802154_tree) {
3094 proto_tree *field_tree;
3095 guint16 metadata = tvb_get_letohs(tvb, offset);
3096
3097 /* Create a subtree for the metadata. */
3098 field_tree = proto_tree_add_subtree_format(ieee802154_tree, tvb, offset, 2, ett_ieee802154_fcs, NULL,
3099 "TI CC24xx-format metadata: FCS %s", (fcs_ok) ? "OK" : "Bad");
3100 /* Display metadata contents. */
3101 proto_tree_add_boolean(field_tree, hf_ieee802154_fcs_ok, tvb, offset, 1, (guint32) (metadata & IEEE802154_CC24xx_CRC_OK));
3102 proto_tree_add_int(field_tree, hf_ieee802154_rssi, tvb, offset++, 1, (gint8) (metadata & IEEE802154_CC24xx_RSSI));
3103 proto_tree_add_uint(field_tree, hf_ieee802154_correlation, tvb, offset, 1, (guint8) ((metadata & IEEE802154_CC24xx_CORRELATION) >> 8));
3104 }
3105 } /* ieee802154_dissect_cc24xx_metadata */
3106
3107 static void
dissect_ieee802154_tap_sun_phy(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint offset,guint length)3108 dissect_ieee802154_tap_sun_phy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint length)
3109 {
3110 (void) pinfo;
3111 if (length == 3) {
3112 guint32 band;
3113 guint32 sun_type;
3114 guint32 mode;
3115 proto_tree_add_item_ret_uint(tree, hf_ieee802154_sun_band, tvb, offset, 1, ENC_LITTLE_ENDIAN, &band);
3116 proto_item_append_text(proto_tree_get_parent(tree), ": Band: %s (%u)", val_to_str_const(band, sun_bands, "Unknown"), band);
3117 proto_tree_add_item_ret_uint(tree, hf_ieee802154_sun_type, tvb, offset+1, 1, ENC_LITTLE_ENDIAN, &sun_type);
3118 if (sun_type < array_length(sun_types)) {
3119 proto_item_append_text(proto_tree_get_parent(tree), ", Type: %s (%u)", val_to_str_const(sun_type, sun_types, "Unknown"), sun_type);
3120 }
3121
3122 switch (sun_type) {
3123 case IEEE802154_SUN_TYPE_FSK_A:
3124 proto_tree_add_item_ret_uint(tree, hf_ieee802154_mode_fsk_a, tvb, offset+2, 1, ENC_LITTLE_ENDIAN, &mode);
3125 proto_item_append_text(proto_tree_get_parent(tree), ", Mode: %u", mode);
3126 break;
3127 case IEEE802154_SUN_TYPE_FSK_B:
3128 proto_tree_add_item_ret_uint(tree, hf_ieee802154_mode_fsk_b, tvb, offset+2, 1, ENC_LITTLE_ENDIAN, &mode);
3129 proto_item_append_text(proto_tree_get_parent(tree), ", Mode: %u", mode);
3130 break;
3131 case IEEE802154_SUN_TYPE_OQPSK_A:
3132 proto_tree_add_item_ret_uint(tree, hf_ieee802154_mode_oqpsk_a, tvb, offset+2, 1, ENC_LITTLE_ENDIAN, &mode);
3133 proto_item_append_text(proto_tree_get_parent(tree), ", Mode: %u", mode);
3134 break;
3135 case IEEE802154_SUN_TYPE_OQPSK_B:
3136 proto_tree_add_item_ret_uint(tree, hf_ieee802154_mode_oqpsk_b, tvb, offset+2, 1, ENC_LITTLE_ENDIAN, &mode);
3137 proto_item_append_text(proto_tree_get_parent(tree), ", Mode: %u", mode);
3138 break;
3139 case IEEE802154_SUN_TYPE_OQPSK_C:
3140 proto_tree_add_item_ret_uint(tree, hf_ieee802154_mode_oqpsk_c, tvb, offset+2, 1, ENC_LITTLE_ENDIAN, &mode);
3141 proto_item_append_text(proto_tree_get_parent(tree), ", Mode: %u", mode);
3142 break;
3143 case IEEE802154_SUN_TYPE_OFDM_OPT1:
3144 case IEEE802154_SUN_TYPE_OFDM_OPT2:
3145 case IEEE802154_SUN_TYPE_OFDM_OPT3:
3146 case IEEE802154_SUN_TYPE_OFDM_OPT4:
3147 proto_tree_add_item_ret_uint(tree, hf_ieee802154_mode_ofdm, tvb, offset+2, 1, ENC_LITTLE_ENDIAN, &mode);
3148 proto_item_append_text(proto_tree_get_parent(tree), ", Mode: %u", mode);
3149 break;
3150 default:
3151 proto_tree_add_item(tree, hf_ieee802154_sun_mode, tvb, offset+2, 1, ENC_LITTLE_ENDIAN);
3152 break;
3153 } /* switch (sun_type) */
3154 }
3155 } /* dissect_ieee802154_tap_sun_phy */
3156
3157 /**
3158 * Create a tree for a TAP TLV
3159 *
3160 * @param tree the tree to append this item to
3161 * @param tvb the tv buffer
3162 * @param offset offset into the tvbuff to begin dissection
3163 * @param type TLV type
3164 * @param length TLV length
3165 * @returns the tree created for the Payload IE
3166 */
3167 static proto_tree*
ieee802154_create_tap_tlv_tree(proto_tree * tree,tvbuff_t * tvb,gint offset,guint32 * type,guint32 * length)3168 ieee802154_create_tap_tlv_tree(proto_tree *tree, tvbuff_t *tvb, gint offset, guint32 *type, guint32 *length)
3169 {
3170 proto_tree *subtree = NULL;
3171 proto_item *ti = NULL;
3172 guint32 subtree_length;
3173
3174 *length = tvb_get_letohs(tvb, offset+2);
3175
3176 subtree_length = 4 + *length;
3177 if (*length % 4) {
3178 subtree_length += (4 - *length % 4);
3179 }
3180
3181 subtree = proto_tree_add_subtree(tree, tvb, offset, subtree_length, ett_ieee802154_tap_tlv, &ti, "");
3182
3183 /* Check if we have a valid TLV */
3184 proto_tree_add_item_ret_uint(subtree, hf_ieee802154_tap_tlv_type, tvb, offset, 2, ENC_LITTLE_ENDIAN, type);
3185 if (*type < array_length(tap_tlv_types)) {
3186 proto_item_append_text(ti, "%s", val_to_str_const(*type, tap_tlv_types, "Unknown"));
3187 }
3188 else {
3189 expert_add_info(NULL, ti, &ei_ieee802154_tap_tlv_invalid_type);
3190 }
3191
3192 proto_tree_add_item(subtree, hf_ieee802154_tap_tlv_length, tvb, offset+2, 2, ENC_LITTLE_ENDIAN);
3193 if (!tvb_bytes_exist(tvb, offset+4, *length)) {
3194 expert_add_info(NULL, ti, &ei_ieee802154_tap_tlv_invalid_length);
3195 }
3196 return subtree;
3197 } /* ieee802154_create_tap_tlv_tree */
3198
3199 static ieee802154_fcs_type_t
dissect_ieee802154_tap_tlvs(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree)3200 dissect_ieee802154_tap_tlvs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
3201 {
3202 guint32 type;
3203 guint32 length;
3204 gint offset = 0;
3205 proto_item *ti;
3206 proto_tree *tlvtree;
3207 guint32 tap_fcs_type;
3208 const char *type_str;
3209 nstime_t nstime;
3210 guint64 frame_start_ts = 0;
3211 guint64 frame_end_ts = 0;
3212 guint64 slot_start_ts = 0;
3213 double delta_us = 0;
3214 guint32 timeslot_length = 0;
3215
3216 /* Default the FCS type to NONE when parsing TAP packets */
3217 tap_fcs_type = IEEE802154_FCS_TYPE_NONE;
3218
3219 while (tvb_bytes_exist(tvb, offset, 4)) {
3220 tlvtree = ieee802154_create_tap_tlv_tree(tree, tvb, offset, &type, &length);
3221 offset += 4;
3222
3223 switch (type) {
3224 case IEEE802154_TAP_FCS_TYPE:
3225 ti = proto_tree_add_item_ret_uint(tlvtree, hf_ieee802154_tap_fcs_type, tvb, offset, 1,
3226 ENC_LITTLE_ENDIAN, &tap_fcs_type);
3227 type_str = try_val_to_str(tap_fcs_type, tap_fcs_type_names);
3228 if (type_str == NULL) {
3229 /* Invalid - flag it as such */
3230 expert_add_info(NULL, ti, &ei_ieee802154_tap_tlv_invalid_fcs_type);
3231
3232 /* Use "Unknown" for the parent */
3233 type_str = "Unknown";
3234 }
3235 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %s (%u)",
3236 type_str, tap_fcs_type);
3237 break;
3238 case IEEE802154_TAP_RSS: {
3239 gfloat rss = tvb_get_ieee_float(tvb, offset, ENC_LITTLE_ENDIAN);
3240 proto_tree_add_float_format_value(tlvtree, hf_ieee802154_tap_rss, tvb, offset, 4, rss, "%.2f dBm", rss);
3241 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %.2f dBm", rss);
3242 break;
3243 }
3244 case IEEE802154_TAP_BIT_RATE: {
3245 guint32 bitrate;
3246 proto_tree_add_item_ret_uint(tlvtree, hf_ieee802154_bit_rate, tvb, offset, 4, ENC_LITTLE_ENDIAN, &bitrate);
3247 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %.3f kbps", bitrate/1000.0);
3248 break;
3249 }
3250 case IEEE802154_TAP_CHANNEL_ASSIGNMENT: {
3251 guint32 channel;
3252 guint32 page;
3253 proto_tree_add_item_ret_uint(tlvtree, hf_ieee802154_ch_num, tvb, offset, 2, ENC_LITTLE_ENDIAN, &channel);
3254 proto_tree_add_item_ret_uint(tlvtree, hf_ieee802154_ch_page, tvb, offset+2, 1, ENC_LITTLE_ENDIAN, &page);
3255 proto_item_append_text(proto_tree_get_parent(tlvtree), ": Page: %s (%u), Number: %u", val_to_str_const(page, channel_page_names, "Unknown"), page, channel);
3256 break;
3257 }
3258 case IEEE802154_TAP_SUN_PHY_INFO:
3259 dissect_ieee802154_tap_sun_phy(tvb, pinfo, tlvtree, offset, length);
3260 break;
3261 case IEEE802154_TAP_START_OF_FRAME_TS:
3262 proto_tree_add_item_ret_uint64(tlvtree, hf_ieee802154_sof_ts, tvb, offset, 8,
3263 ENC_LITTLE_ENDIAN, &frame_start_ts);
3264 nstime.secs = (time_t)frame_start_ts / 1000000000L;
3265 nstime.nsecs = frame_start_ts % 1000000000UL;
3266 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %s s", rel_time_to_secs_str(pinfo->pool, &nstime));
3267 break;
3268 case IEEE802154_TAP_END_OF_FRAME_TS:
3269 proto_tree_add_item_ret_uint64(tlvtree, hf_ieee802154_eof_ts, tvb, offset, 8,
3270 ENC_LITTLE_ENDIAN, &frame_end_ts);
3271 nstime.secs = (time_t)frame_end_ts / 1000000000L;
3272 nstime.nsecs = frame_end_ts % 1000000000UL;
3273 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %s s", rel_time_to_secs_str(pinfo->pool, &nstime));
3274 break;
3275 case IEEE802154_TAP_ASN:
3276 proto_tree_add_item_ret_uint64(tlvtree, hf_ieee802154_asn, tvb, offset, 8, ENC_LITTLE_ENDIAN, &ieee802154_tsch_asn);
3277 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %"G_GUINT64_FORMAT, ieee802154_tsch_asn);
3278 break;
3279 case IEEE802154_TAP_SLOT_START_TS:
3280 proto_tree_add_item_ret_uint64(tlvtree, hf_ieee802154_slot_start_ts, tvb, offset, 8,
3281 ENC_LITTLE_ENDIAN, &slot_start_ts);
3282 nstime.secs = (time_t)slot_start_ts / 1000000000L;
3283 nstime.nsecs = slot_start_ts % 1000000000UL;
3284 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %s s", rel_time_to_secs_str(pinfo->pool, &nstime));
3285 break;
3286 case IEEE802154_TAP_TIMESLOT_LENGTH:
3287 proto_tree_add_item_ret_uint(tlvtree, hf_ieee802154_tap_timeslot_length, tvb, offset, 4,
3288 ENC_LITTLE_ENDIAN, ×lot_length);
3289 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %"G_GUINT32_FORMAT" %s", timeslot_length, units_microseconds.singular);
3290 break;
3291 case IEEE802154_TAP_LQI: {
3292 guint32 lqi;
3293 proto_tree_add_item_ret_uint(tlvtree, hf_ieee802154_tap_lqi, tvb, offset, 1, ENC_LITTLE_ENDIAN, &lqi);
3294 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %u", lqi);
3295 break;
3296 }
3297 case IEEE802154_TAP_CHANNEL_FREQUENCY: {
3298 gfloat freq = tvb_get_ieee_float(tvb, offset, ENC_LITTLE_ENDIAN);
3299 proto_tree_add_float_format_value(tlvtree, hf_ieee802154_ch_freq, tvb, offset, 4, freq, "%.3f kHz", freq);
3300 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %.3f kHz", freq);
3301 break;
3302 }
3303 case IEEE802154_TAP_CHANNEL_PLAN: {
3304 guint32 count;
3305 gfloat ch0_freq = tvb_get_ieee_float(tvb, offset, ENC_LITTLE_ENDIAN);
3306 gfloat spacing = tvb_get_ieee_float(tvb, offset+4, ENC_LITTLE_ENDIAN);
3307 proto_tree_add_float_format_value(tlvtree, hf_ieee802154_chplan_start, tvb, offset, 4, ch0_freq, "%.3f kHz", ch0_freq);
3308 proto_item_append_text(proto_tree_get_parent(tlvtree), ": Start %.3f kHz", ch0_freq);
3309 proto_tree_add_float_format_value(tlvtree, hf_ieee802154_chplan_spacing, tvb, offset+4, 4, spacing, "%.3f kHz", spacing);
3310 proto_item_append_text(proto_tree_get_parent(tlvtree), ", Spacing %.3f kHz", spacing);
3311 proto_tree_add_item_ret_uint(tlvtree, hf_ieee802154_chplan_channels, tvb, offset+8, 2, ENC_LITTLE_ENDIAN, &count);
3312 proto_item_append_text(proto_tree_get_parent(tlvtree), ", Channels %u", count);
3313 break;
3314 }
3315 default:
3316 proto_tree_add_item(tlvtree, hf_ieee802154_tap_tlv_unknown, tvb, offset, length, ENC_NA);
3317 proto_item_append_text(proto_tree_get_parent(tlvtree), "Unknown TLV");
3318 break;
3319 } /* switch (tlv_type) */
3320
3321 if (length%4) {
3322 guint32 zero = 0;
3323 GByteArray *padding = g_byte_array_sized_new(4);
3324 ti = proto_tree_add_bytes_item(tlvtree, hf_ieee802154_tap_tlv_padding, tvb, offset+length, 4-length%4, ENC_NA, padding, NULL, NULL);
3325 if (memcmp(&zero, padding->data, 4-length%4)) {
3326 expert_add_info(NULL, ti, &ei_ieee802154_tap_tlv_padding_not_zeros);
3327 }
3328 g_byte_array_free(padding, TRUE);
3329 }
3330 offset += ROUND_UP(length, 4);
3331 } /* while */
3332
3333 /* if we have both slot start and frame start timestamp, show frame start offset */
3334 if (slot_start_ts && frame_start_ts) {
3335 delta_us = (double)(frame_start_ts - slot_start_ts) / 1000;
3336 ti = proto_tree_add_double_format_value(tree, hf_ieee802154_frame_start_offset, NULL, 0, 0, delta_us, "%.3f %s", delta_us, units_microseconds.singular);
3337 proto_item_set_generated(ti);
3338 }
3339
3340 /* if we have both start and end frame timestamp, show frame duration */
3341 if (frame_start_ts && frame_end_ts) {
3342 delta_us = (double)(frame_end_ts - frame_start_ts) / 1000;
3343 ti = proto_tree_add_double_format_value(tree, hf_ieee802154_frame_duration, NULL, 0, 0, delta_us, "%.3f %s", delta_us, units_microseconds.singular);
3344 proto_item_set_generated(ti);
3345 }
3346
3347 /* if we have start of slot, timeslot length, and end of frame timestamp, show frame overflow (+ve) or underflow (-ve) */
3348 if (timeslot_length && frame_end_ts && slot_start_ts) {
3349 /* overflow = frame_end_ts - slot_start_ts - timeslot_length */
3350 delta_us = (double)(frame_end_ts - slot_start_ts) / 1000;
3351 delta_us -= timeslot_length;
3352 ti = proto_tree_add_double_format_value(tree, hf_ieee802154_frame_end_offset, NULL, 0, 0, delta_us, "%.3f %s", delta_us, units_microseconds.singular);
3353 proto_item_set_generated(ti);
3354 }
3355
3356 return (ieee802154_fcs_type_t)tap_fcs_type;
3357 } /* dissect_ieee802154_tap_tlvs */
3358
3359 /*
3360 * Information Elements Processing (IEs)
3361 */
3362
3363 /**
3364 * Create a tree for a Payload IE incl. the TLV header and append the IE name to the parent item
3365 *
3366 * @param tvb the tv buffer
3367 * @param tree the tree to append this item to
3368 * @param hf field index
3369 * @param ett tree index
3370 * @returns the tree created for the Payload IE
3371 */
3372 proto_tree*
ieee802154_create_pie_tree(tvbuff_t * tvb,proto_tree * tree,int hf,gint ett)3373 ieee802154_create_pie_tree(tvbuff_t *tvb, proto_tree *tree, int hf, gint ett)
3374 {
3375 proto_item *subitem;
3376 proto_tree *subtree;
3377 header_field_info *hfinfo;
3378 static int * const tlv_fields[] = {
3379 &hf_ieee802154_payload_ie_type,
3380 &hf_ieee802154_payload_ie_id,
3381 &hf_ieee802154_payload_ie_length,
3382 NULL
3383 };
3384
3385 subitem = proto_tree_add_item(tree, hf, tvb, 0, tvb_reported_length(tvb), ENC_NA);
3386 subtree = proto_item_add_subtree(subitem, ett);
3387 proto_tree_add_bitmask_with_flags(subtree, tvb, 0, hf_ieee802154_payload_ie_tlv, ett_ieee802154_payload_ie_tlv,
3388 tlv_fields, ENC_LITTLE_ENDIAN, BMT_NO_FLAGS);
3389
3390 hfinfo = proto_registrar_get_nth(hf);
3391 if (hfinfo && hfinfo->name) {
3392 proto_item_append_text(proto_tree_get_parent(tree), ", %s", hfinfo->name);
3393 }
3394 return subtree;
3395 }
3396
3397 /**
3398 * Create a tree for a Payload Sub-IE incl. the TLV header and append the IE name to the parent item
3399 *
3400 * @param tvb the tv buffer
3401 * @param tree the tree to append this item to
3402 * @param hf field index
3403 * @param ett tree index
3404 * @returns the tree created for the Payload IE
3405 */
3406 static proto_tree*
ieee802154_create_psie_tree(tvbuff_t * tvb,proto_tree * tree,int hf,gint ett)3407 ieee802154_create_psie_tree(tvbuff_t *tvb, proto_tree *tree, int hf, gint ett)
3408 {
3409 proto_item *subitem;
3410 proto_tree *subtree;
3411 header_field_info *hfinfo;
3412
3413 subitem = proto_tree_add_item(tree, hf, tvb, 0, tvb_reported_length(tvb), ENC_NA);
3414 subtree = proto_item_add_subtree(subitem, ett);
3415 if (tvb_get_letohs(tvb, 0) & IEEE802154_PSIE_TYPE_MASK) {
3416 static int * const fields_long[] = {
3417 &hf_ieee802154_psie_type,
3418 &hf_ieee802154_psie_id_long,
3419 &hf_ieee802154_psie_length_long,
3420 NULL
3421 };
3422 proto_tree_add_bitmask(subtree, tvb, 0, hf_ieee802154_psie, ett_ieee802154_psie, fields_long, ENC_LITTLE_ENDIAN);
3423 }
3424 else {
3425 static int * const fields_short[] = {
3426 &hf_ieee802154_psie_type,
3427 &hf_ieee802154_psie_id_short,
3428 &hf_ieee802154_psie_length_short,
3429 NULL
3430 };
3431 proto_tree_add_bitmask(subtree, tvb, 0, hf_ieee802154_psie, ett_ieee802154_psie, fields_short, ENC_LITTLE_ENDIAN);
3432 }
3433
3434 hfinfo = proto_registrar_get_nth(hf);
3435 if (hfinfo && hfinfo->name) {
3436 proto_item_append_text(proto_tree_get_parent(tree), ", %s", hfinfo->name);
3437 }
3438 return subtree;
3439 }
3440
3441 /**
3442 * Subdissector for the MLME Channel Hopping Payload IE
3443 */
3444 static int
dissect_802154_channel_hopping(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)3445 dissect_802154_channel_hopping(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
3446 {
3447 proto_tree *subtree = ieee802154_create_psie_tree(tvb, tree, hf_ieee802154_tsch_channel_hopping, ett_ieee802154_mlme_payload);
3448
3449 proto_tree_add_item(subtree, hf_ieee802154_tsch_hopping_sequence_id, tvb, 2, 1, ENC_LITTLE_ENDIAN);
3450
3451 if (tvb_reported_length_remaining(tvb, 3) > 1) {
3452 /* TODO: There's still a huge amount of optional stuff that could follow */
3453 proto_tree_add_item(subtree, hf_ieee802154_mlme_ie_data, tvb, 3, tvb_reported_length_remaining(tvb, 3), ENC_NA);
3454 }
3455 return tvb_reported_length(tvb);
3456 } /* dissect_802154_channel_hopping */
3457
3458 /**
3459 * Subdissector for the Nested MLME IE for TSCH Synchronization
3460 */
3461 static int
dissect_802154_tsch_time_sync(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)3462 dissect_802154_tsch_time_sync(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
3463 {
3464 proto_tree *subtree = ieee802154_create_psie_tree(tvb, tree, hf_ieee802154_tsch_sync, ett_ieee802154_tsch_synch);
3465
3466 proto_tree_add_item(subtree, hf_ieee802154_tsch_asn, tvb, 2, 5, ENC_LITTLE_ENDIAN);
3467 proto_tree_add_item(subtree, hf_ieee802154_tsch_join_metric, tvb, 7, 1, ENC_LITTLE_ENDIAN);
3468 return 8;
3469 }/* dissect_802154_tsch_time_sync*/
3470
3471 /**
3472 * Subdissector for the Nested MLME IE for TSCH Slotframe and Link
3473 */
3474 static int
dissect_802154_tsch_slotframe_link(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)3475 dissect_802154_tsch_slotframe_link(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
3476 {
3477 guint8 nb_slotframes;
3478 guint8 slotframe_index;
3479 proto_tree *subtree;
3480 guint offset = 0;
3481
3482 subtree = ieee802154_create_psie_tree(tvb, tree, hf_ieee802154_tsch_slotframe, ett_ieee802154_tsch_slotframe);
3483 offset += 2;
3484
3485 nb_slotframes = tvb_get_guint8(tvb, offset);
3486 proto_tree_add_item(subtree, hf_ieee802154_tsch_slotf_link_nb_slotf, tvb, offset, 1, ENC_LITTLE_ENDIAN);
3487 offset += 1;
3488
3489 for (slotframe_index = 1; slotframe_index <= nb_slotframes; slotframe_index++) {
3490 /* Create a tree for the slotframe. */
3491 guint8 nb_links = tvb_get_guint8(tvb, offset + 3);
3492 proto_item *sf_item = proto_tree_add_subtree_format(subtree, tvb, offset, 4 + (5 * nb_links),
3493 ett_ieee802154_tsch_slotframe, NULL,
3494 "Slotframes [%u]", slotframe_index);
3495 proto_tree *sf_tree = proto_item_add_subtree(sf_item, ett_ieee802154_tsch_slotframe_list);
3496 proto_tree_add_item(sf_tree, hf_ieee802154_tsch_slotf_link_slotf_handle, tvb, offset, 1, ENC_LITTLE_ENDIAN);
3497 proto_tree_add_item(sf_tree, hf_ieee802154_tsch_slotf_size, tvb, offset + 1, 2, ENC_LITTLE_ENDIAN);
3498 proto_tree_add_item(sf_tree, hf_ieee802154_tsch_slotf_link_nb_links, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
3499
3500 /* Create a tree for each link in the slotframe. */
3501 offset += 4;
3502 while (nb_links > 0) {
3503 static int * const fields_options[] = {
3504 &hf_ieee802154_tsch_slotf_link_options_tx,
3505 &hf_ieee802154_tsch_slotf_link_options_rx,
3506 &hf_ieee802154_tsch_slotf_link_options_shared,
3507 &hf_ieee802154_tsch_slotf_link_options_timkeeping,
3508 &hf_ieee802154_tsch_slotf_link_options_priority,
3509 NULL
3510 };
3511
3512 proto_item *link_item = proto_tree_add_item(sf_tree, hf_ieee802154_tsch_link_info, tvb, offset, 5, ENC_NA);
3513 proto_tree *link_tree = proto_item_add_subtree(link_item, ett_ieee802154_tsch_slotframe_link);
3514 proto_tree_add_item(link_tree, hf_ieee802154_tsch_slotf_link_timeslot, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3515 proto_tree_add_item(link_tree, hf_ieee802154_tsch_slotf_link_channel_offset, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN);
3516 proto_tree_add_bitmask(link_tree, tvb, offset + 4, hf_ieee802154_tsch_slotf_link_options, ett_ieee802154_tsch_slotframe_link_options, fields_options, ENC_LITTLE_ENDIAN);
3517 nb_links -= 1;
3518 offset += 5;
3519 }
3520 }
3521
3522 return offset;
3523 }/* dissect_802154_tsch_slotframe_link */
3524
3525 /**
3526 * Subdissector for the Nested MLME IE for TSCH Timeslot Description
3527 */
3528 static int
dissect_802154_tsch_timeslot(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)3529 dissect_802154_tsch_timeslot(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
3530 {
3531 proto_tree *subtree = ieee802154_create_psie_tree(tvb, tree, hf_ieee802154_tsch_timeslot, ett_ieee802154_tsch_timeslot);
3532 guint offset = 2;
3533
3534 proto_tree_add_item(subtree, hf_ieee802154_tsch_timeslot_id, tvb, 2, 1, ENC_LITTLE_ENDIAN);
3535 offset++;
3536
3537 if (tvb_reported_length(tvb) > offset) {
3538 const int timeslot_fields[] = {
3539 hf_ieee802154_tsch_timeslot_cca_offset,
3540 hf_ieee802154_tsch_timeslot_cca,
3541 hf_ieee802154_tsch_timeslot_tx_offset,
3542 hf_ieee802154_tsch_timeslot_rx_offset,
3543 hf_ieee802154_tsch_timeslot_rx_ack_delay,
3544 hf_ieee802154_tsch_timeslot_tx_ack_delay,
3545 hf_ieee802154_tsch_timeslot_rx_wait,
3546 hf_ieee802154_tsch_timeslot_ack_wait,
3547 hf_ieee802154_tsch_timeslot_turnaround,
3548 hf_ieee802154_tsch_timeslot_max_ack,
3549 };
3550 unsigned int i;
3551 for (i = 0; i < sizeof(timeslot_fields)/sizeof(timeslot_fields[1]); i++) {
3552 proto_tree_add_item(subtree, timeslot_fields[i], tvb, offset, 2, ENC_LITTLE_ENDIAN);
3553 offset += 2;
3554 }
3555
3556 /* The last two fields are may have different encodings depending on the length of the IE. */
3557 if (tvb_reported_length_remaining(tvb, offset) > 4) {
3558 proto_tree_add_item(subtree, hf_ieee802154_tsch_timeslot_max_tx, tvb, offset, 3, ENC_LITTLE_ENDIAN);
3559 offset += 3;
3560 proto_tree_add_item(subtree, hf_ieee802154_tsch_timeslot_length, tvb, offset, 3, ENC_LITTLE_ENDIAN);
3561 offset += 3;
3562 }
3563 else {
3564 proto_tree_add_item(subtree, hf_ieee802154_tsch_timeslot_max_tx, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3565 offset += 2;
3566 proto_tree_add_item(subtree, hf_ieee802154_tsch_timeslot_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3567 offset += 2;
3568 }
3569 }
3570 return offset;
3571 } /* dissect_802154_tsch_timeslot */
3572
3573 /**
3574 * Subdissector for the 6TOP Protocol contained within the Payload Information Elements.
3575 */
3576 static int
dissect_ietf_ie(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * ies_tree,void * data _U_)3577 dissect_ietf_ie(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *ies_tree, void *data _U_)
3578 {
3579 const guint8 supported_6p_version = 0x00;
3580
3581 proto_tree *p_inf_elem_tree = ieee802154_create_pie_tree(tvb, ies_tree, hf_ieee802154_pie_ietf, ett_ieee802154_pie_ietf);
3582 guint offset = 2;
3583 guint pie_length = tvb_reported_length(tvb) - 2;
3584 guint8 subie;
3585 guint8 version;
3586 guint8 type;
3587 guint8 code;
3588 guint8 num_cells = 0;
3589 gboolean have_cell_list = FALSE;
3590 int i;
3591 proto_item *sixtop_item = NULL;
3592 proto_tree *sixtop_tree = NULL;
3593 proto_item *cell_list_item = NULL;
3594 proto_tree *cell_list_tree = NULL;
3595 proto_item *cell_item = NULL;
3596 proto_tree *cell_tree = NULL;
3597 proto_item *type_item = NULL;
3598 proto_item *code_item = NULL;
3599 const gchar *code_str = NULL;
3600 static int * const cell_options[] = {
3601 &hf_ieee802154_6top_cell_option_tx,
3602 &hf_ieee802154_6top_cell_option_rx,
3603 &hf_ieee802154_6top_cell_option_shared,
3604 &hf_ieee802154_6top_cell_option_reserved,
3605 NULL
3606 };
3607
3608 if (pie_length < 5) {
3609 return pie_length + 2;
3610 }
3611
3612 subie = tvb_get_guint8(tvb, offset);
3613 version = tvb_get_guint8(tvb, offset + 1) & IETF_6TOP_VERSION;
3614
3615 if (subie != IEEE802154_IETF_SUBIE_6TOP || version != supported_6p_version) {
3616 return pie_length + 2;
3617 }
3618
3619 type = (tvb_get_guint8(tvb, offset + 1) & IETF_6TOP_TYPE) >> 4;
3620 code = tvb_get_guint8(tvb, offset + 2);
3621
3622 proto_tree_add_item(p_inf_elem_tree, hf_ieee802154_p_ie_ietf_sub_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
3623
3624 sixtop_item = proto_tree_add_item(p_inf_elem_tree, hf_ieee802154_6top, tvb, offset, pie_length, ENC_NA);
3625 sixtop_tree = proto_item_add_subtree(sixtop_item, ett_ieee802154_p_ie_6top);
3626
3627 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_version, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
3628 type_item = proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_type, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
3629 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_flags_reserved, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
3630 code_item = proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_code, tvb, offset + 2, 1, ENC_LITTLE_ENDIAN);
3631 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_sfid, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
3632 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_seqnum, tvb, offset + 4, 1, ENC_LITTLE_ENDIAN);
3633
3634 col_set_str(pinfo->cinfo, COL_PROTOCOL, "6top");
3635 if (type == IETF_6TOP_TYPE_REQUEST) {
3636 code_str = val_to_str_const(code, ietf_6top_command_identifiers,"Unknown");
3637 col_add_fstr(pinfo->cinfo, COL_INFO, "6P %s Request", code_str);
3638 } else {
3639 code_str = val_to_str_const(code, ietf_6top_return_codes,"Unknown");
3640 col_add_fstr(pinfo->cinfo, COL_INFO, "6P %s (%s)",
3641 val_to_str_const(type, ietf_6top_types,"Unknown"), code_str);
3642 }
3643 proto_item_append_text(code_item, " (%s)", code_str);
3644
3645 offset += 5;
3646 pie_length -= 5;
3647
3648 if (type == IETF_6TOP_TYPE_REQUEST) {
3649 switch (code) {
3650 case IETF_6TOP_CMD_ADD:
3651 case IETF_6TOP_CMD_DELETE:
3652 case IETF_6TOP_CMD_RELOCATE:
3653 if (pie_length < 4) {
3654 break;
3655 }
3656 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_metadata, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3657 proto_tree_add_bitmask(sixtop_tree, tvb, offset + 2, hf_ieee802154_6top_cell_options, ett_ieee802154_p_ie_6top_cell_options, cell_options, ENC_LITTLE_ENDIAN);
3658 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_num_cells, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
3659 num_cells = tvb_get_guint8(tvb, offset + 3);
3660 pie_length -= 4;
3661 offset += 4;
3662 if (pie_length > 0 && (pie_length % 4) == 0) {
3663 have_cell_list = TRUE;
3664 }
3665 break;
3666 case IETF_6TOP_CMD_COUNT:
3667 if (pie_length < 3) {
3668 break;
3669 }
3670 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_metadata, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3671 proto_tree_add_bitmask(sixtop_tree, tvb, offset + 2, hf_ieee802154_6top_cell_options, ett_ieee802154_p_ie_6top_cell_options, cell_options, ENC_LITTLE_ENDIAN);
3672 pie_length -= 3;
3673 offset += 3;
3674 break;
3675 case IETF_6TOP_CMD_LIST:
3676 if (pie_length != 8) {
3677 break;
3678 }
3679 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_metadata, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3680 proto_tree_add_bitmask(sixtop_tree, tvb, offset + 2, hf_ieee802154_6top_cell_options, ett_ieee802154_p_ie_6top_cell_options, cell_options, ENC_LITTLE_ENDIAN);
3681 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_reserved, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
3682 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_offset, tvb, offset + 4, 2, ENC_LITTLE_ENDIAN);
3683 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_max_num_cells, tvb, offset + 6, 2, ENC_LITTLE_ENDIAN);
3684 pie_length -= 8;
3685 offset += 8;
3686 break;
3687 case IETF_6TOP_CMD_SIGNAL:
3688 if (pie_length < 2) {
3689 break;
3690 }
3691 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_metadata, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3692 if (pie_length > 2) {
3693 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_payload, tvb, offset + 2, pie_length - 2, ENC_NA);
3694 }
3695 offset += pie_length;
3696 pie_length = 0;
3697 break;
3698 case IETF_6TOP_CMD_CLEAR:
3699 if (pie_length < 2) {
3700 break;
3701 }
3702 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_metadata, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3703 pie_length -= 2;
3704 offset += 2;
3705 break;
3706 default:
3707 /* unsupported command */
3708 expert_add_info(pinfo, code_item, &ei_ieee802154_6top_unsupported_command);
3709 break;
3710 }
3711 } else if (type == IETF_6TOP_TYPE_RESPONSE || type == IETF_6TOP_TYPE_CONFIRMATION) {
3712 switch(code) {
3713 case IETF_6TOP_RC_SUCCESS:
3714 if (pie_length > 0) {
3715 if (pie_length == 2) {
3716 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_total_num_cells, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3717 pie_length -= 2;
3718 offset += 2;
3719 } else if ((pie_length % 4) == 0) {
3720 have_cell_list = TRUE;
3721 } else {
3722 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_payload, tvb, offset, pie_length, ENC_NA);
3723 offset += pie_length;
3724 pie_length = 0;
3725 }
3726 }
3727 break;
3728 case IETF_6TOP_RC_EOL:
3729 if(pie_length > 0 && (pie_length % 4) == 0) {
3730 have_cell_list = TRUE;
3731 }
3732 break;
3733 case IETF_6TOP_RC_ERR:
3734 case IETF_6TOP_RC_RESET:
3735 case IETF_6TOP_RC_ERR_VERSION:
3736 case IETF_6TOP_RC_ERR_SFID:
3737 case IETF_6TOP_RC_ERR_SEQNUM:
3738 case IETF_6TOP_RC_ERR_CELLLIST:
3739 case IETF_6TOP_RC_ERR_BUSY:
3740 case IETF_6TOP_RC_ERR_LOCKED:
3741 /* They have no other field */
3742 break;
3743 default:
3744 /* unsupported return code */
3745 expert_add_info(pinfo, code_item, &ei_ieee802154_6top_unsupported_return_code);
3746 break;
3747 }
3748 } else {
3749 /* unsupported type */
3750 expert_add_info(pinfo, type_item, &ei_ieee802154_6top_unsupported_type);
3751 }
3752
3753 if (have_cell_list) {
3754 if (type == IETF_6TOP_TYPE_REQUEST && code == IETF_6TOP_CMD_RELOCATE) {
3755 cell_list_item = proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_rel_cell_list, tvb, offset, pie_length, ENC_NA);
3756 cell_list_tree = proto_item_add_subtree(cell_list_item, ett_ieee802154_p_ie_6top_rel_cell_list);
3757 /* num_cells is expected to be set properly */
3758 for (i = 0; i < num_cells; offset += 4, i++) {
3759 cell_item = proto_tree_add_item(cell_list_tree, hf_ieee802154_6top_cell, tvb, offset, 4, ENC_NA);
3760 cell_tree = proto_item_add_subtree(cell_item, ett_ieee802154_p_ie_6top_cell);
3761 proto_tree_add_item(cell_tree, hf_ieee802154_6top_slot_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3762 proto_tree_add_item(cell_tree, hf_ieee802154_6top_channel_offset, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN);
3763 }
3764 pie_length -= num_cells * 4;
3765 cell_list_item = proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_cand_cell_list, tvb, offset, pie_length, ENC_NA);
3766 cell_list_tree = proto_item_add_subtree(cell_list_item, ett_ieee802154_p_ie_6top_cand_cell_list);
3767 for (i = 0; pie_length > 0; pie_length -= 4, offset += 4, i++) {
3768 cell_item = proto_tree_add_item(cell_list_tree, hf_ieee802154_6top_cell, tvb, offset, 4, ENC_NA);
3769 cell_tree = proto_item_add_subtree(cell_item, ett_ieee802154_p_ie_6top_cell);
3770 proto_tree_add_item(cell_tree, hf_ieee802154_6top_slot_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3771 proto_tree_add_item(cell_tree, hf_ieee802154_6top_channel_offset, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN);
3772 }
3773 } else {
3774 cell_list_item = proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_cell_list, tvb, offset, pie_length, ENC_NA);
3775 cell_list_tree = proto_item_add_subtree(cell_list_item, ett_ieee802154_p_ie_6top_cell_list);
3776 for (i = 0; pie_length > 0; pie_length -= 4, offset += 4, i++) {
3777 cell_item = proto_tree_add_item(cell_list_tree, hf_ieee802154_6top_cell, tvb, offset, 4, ENC_NA);
3778 cell_tree = proto_item_add_subtree(cell_item, ett_ieee802154_p_ie_6top_cell);
3779 proto_tree_add_item(cell_tree, hf_ieee802154_6top_slot_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3780 proto_tree_add_item(cell_tree, hf_ieee802154_6top_channel_offset, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN);
3781 }
3782 }
3783 }
3784
3785 return offset;
3786 } /* dissect_ieee802154_6top */
3787
3788 /**
3789 * Subdissector for the Superframe specification sub-field within the beacon frame.
3790 *
3791 * @param tvb pointer to buffer containing raw packet.
3792 * @param pinfo pointer to packet information fields (unused).
3793 * @param tree pointer to command subtree.
3794 * @param offset offset into the tvbuff to begin dissection.
3795 */
3796 void
dissect_ieee802154_superframe(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,guint * offset)3797 dissect_ieee802154_superframe(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint *offset)
3798 {
3799 static int * const superframe[] = {
3800 &hf_ieee802154_beacon_order,
3801 &hf_ieee802154_superframe_order,
3802 &hf_ieee802154_cap,
3803 &hf_ieee802154_superframe_battery_ext,
3804 &hf_ieee802154_superframe_coord,
3805 &hf_ieee802154_assoc_permit,
3806 NULL
3807 };
3808
3809 proto_tree_add_bitmask_text(tree, tvb, *offset, 2, "Superframe Specification: ", NULL , ett_ieee802154_superframe, superframe, ENC_LITTLE_ENDIAN, BMT_NO_INT|BMT_NO_TFS);
3810 (*offset) += 2;
3811 } /* dissect_ieee802154_superframe */
3812
3813 /**
3814 * Subdissector for the GTS information fields within the beacon frame.
3815 *
3816 * @param tvb pointer to buffer containing raw packet.
3817 * @param pinfo pointer to packet information fields (unused).
3818 * @param tree pointer to command subtree.
3819 * @param offset offset into the tvbuff to begin dissection.
3820 */
3821 void
dissect_ieee802154_gtsinfo(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,guint * offset)3822 dissect_ieee802154_gtsinfo(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint *offset)
3823 {
3824 proto_tree *field_tree = NULL;
3825 proto_tree *subtree = NULL;
3826 proto_item *ti;
3827 guint8 gts_spec;
3828 guint8 gts_count;
3829
3830 /* Get and display the GTS specification field */
3831 gts_spec = tvb_get_guint8(tvb, *offset);
3832 gts_count = gts_spec & IEEE802154_GTS_COUNT_MASK;
3833 if (tree) {
3834 /* Add Subtree for GTS information. */
3835 if (gts_count) {
3836 field_tree = proto_tree_add_subtree(tree, tvb, *offset, 2 + (gts_count * 3), ett_ieee802154_gts, NULL, "GTS");
3837 }
3838 else {
3839 field_tree = proto_tree_add_subtree(tree, tvb, *offset, 1, ett_ieee802154_gts, NULL, "GTS");
3840 }
3841
3842 proto_tree_add_uint(field_tree, hf_ieee802154_gts_count, tvb, *offset, 1, gts_count);
3843 proto_tree_add_boolean(field_tree, hf_ieee802154_gts_permit, tvb, *offset, 1, gts_spec & IEEE802154_GTS_PERMIT_MASK);
3844 }
3845 (*offset) += 1;
3846
3847 /* If the GTS descriptor count is nonzero, then the GTS directions mask and descriptor list are present. */
3848 if (gts_count) {
3849 guint8 gts_directions = tvb_get_guint8(tvb, *offset);
3850 guint gts_rx = 0;
3851 int i;
3852
3853 /* Display the directions mask. */
3854 if (tree) {
3855 proto_tree *dir_tree;
3856
3857 /* Create a subtree. */
3858 dir_tree = proto_tree_add_subtree(field_tree, tvb, *offset, 1, ett_ieee802154_gts_direction, &ti, "GTS Directions");
3859
3860 /* Add the directions to the subtree. */
3861 for (i=0; i<gts_count; i++) {
3862 gboolean dir = gts_directions & IEEE802154_GTS_DIRECTION_SLOT(i);
3863 proto_tree_add_boolean_format(dir_tree, hf_ieee802154_gts_direction, tvb, *offset, 1, dir, "GTS Slot %i: %s", i+1, dir?"Receive Only":"Transmit Only");
3864 if (dir) gts_rx++;
3865 } /* for */
3866 proto_item_append_text(ti, ": %i Receive & %i Transmit", gts_rx, gts_count - gts_rx);
3867 }
3868 (*offset) += 1;
3869
3870 /* Create a subtree for the GTS descriptors. */
3871 subtree = proto_tree_add_subtree(field_tree, tvb, *offset, gts_count * 3, ett_ieee802154_gts_descriptors, NULL, "GTS Descriptors");
3872
3873 /* Get and display the GTS descriptors. */
3874 for (i=0; i<gts_count; i++) {
3875 guint16 gts_addr = tvb_get_letohs(tvb, (*offset));
3876 guint8 gts_slot = tvb_get_guint8(tvb, (*offset)+2);
3877 guint8 gts_length = (gts_slot & IEEE802154_GTS_LENGTH_MASK) >> IEEE802154_GTS_LENGTH_SHIFT;
3878
3879 gts_slot = (gts_slot & IEEE802154_GTS_SLOT_MASK);
3880
3881 if (tree) {
3882 /* Add address, slot, and time length fields. */
3883 ti = proto_tree_add_uint(subtree, hf_ieee802154_gts_address, tvb, (*offset), 3, gts_addr);
3884 proto_item_append_text(ti, ", Slot: %i", gts_slot);
3885 proto_item_append_text(ti, ", Length: %i", gts_length);
3886 }
3887 (*offset) += 3;
3888 } /* for */
3889 }
3890 } /* dissect_ieee802154_gtsinfo */
3891
3892 /**
3893 * Subdissector for the pending address list fields within the beacon frame.
3894 *
3895 * @param tvb pointer to buffer containing raw packet.
3896 * @param pinfo pointer to packet information fields (unused).
3897 * @param tree pointer to command subtree.
3898 * @param offset into the tvbuff to begin dissection.
3899 */
3900 void
dissect_ieee802154_pendaddr(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,guint * offset)3901 dissect_ieee802154_pendaddr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint *offset)
3902 {
3903 proto_tree *subtree;
3904 guint8 pend_spec;
3905 guint8 pend_num16;
3906 guint8 pend_num64;
3907 int i;
3908
3909 /* Get the Pending Addresses specification fields */
3910 pend_spec = tvb_get_guint8(tvb, *offset);
3911 pend_num16 = pend_spec & IEEE802154_PENDADDR_SHORT_MASK;
3912 pend_num64 = (pend_spec & IEEE802154_PENDADDR_LONG_MASK) >> IEEE802154_PENDADDR_LONG_SHIFT;
3913
3914 /* Add Subtree for the addresses */
3915 subtree = proto_tree_add_subtree_format(tree, tvb, *offset, 1 + 2*pend_num16 + 8*pend_num64,
3916 ett_ieee802154_pendaddr, NULL, "Pending Addresses: %i Short and %i Long", pend_num16, pend_num64);
3917 (*offset) += 1;
3918
3919 for (i=0; i<pend_num16; i++) {
3920 guint16 addr = tvb_get_letohs(tvb, *offset);
3921 proto_tree_add_uint(subtree, hf_ieee802154_pending16, tvb, *offset, 2, addr);
3922 (*offset) += 2;
3923 } /* for */
3924 for (i=0; i<pend_num64; i++) {
3925 proto_tree_add_item(subtree, hf_ieee802154_pending64, tvb, *offset, 8, ENC_LITTLE_ENDIAN);
3926 (*offset) += 8;
3927 } /* for */
3928 } /* dissect_ieee802154_pendaddr */
3929
3930 /*
3931 * Header IEs
3932 */
3933
3934 /**
3935 * Create a tree for a Header IE incl. the TLV header and append the IE name to the parent item
3936 *
3937 * @param tvb the tv buffer
3938 * @param tree the tree to append this item to
3939 * @param hf field index
3940 * @param ett tree index
3941 * @returns the tree created for the Header IE
3942 */
3943 proto_tree*
ieee802154_create_hie_tree(tvbuff_t * tvb,proto_tree * tree,int hf,gint ett)3944 ieee802154_create_hie_tree(tvbuff_t *tvb, proto_tree *tree, int hf, gint ett)
3945 {
3946 proto_item *subitem;
3947 proto_tree *subtree;
3948 header_field_info *hfinfo;
3949 static int * const tlv_fields[] = {
3950 &hf_ieee802154_header_ie_type,
3951 &hf_ieee802154_header_ie_id,
3952 &hf_ieee802154_header_ie_length,
3953 NULL
3954 };
3955
3956 subitem = proto_tree_add_item(tree, hf, tvb, 0, tvb_reported_length(tvb), ENC_NA);
3957 subtree = proto_item_add_subtree(subitem, ett);
3958 proto_tree_add_bitmask_with_flags(subtree, tvb, 0, hf_ieee802154_header_ie_tlv, ett_ieee802154_header_ie_tlv,
3959 tlv_fields, ENC_LITTLE_ENDIAN, BMT_NO_FLAGS);
3960
3961 hfinfo = proto_registrar_get_nth(hf);
3962 if (hfinfo && hfinfo->name) {
3963 proto_item_append_text(proto_tree_get_parent(tree), ", %s", hfinfo->name);
3964 }
3965 return subtree;
3966 }
3967
3968 /*
3969 * The dissectors for the individual Header IEs
3970 * They are called via call_dissector with the tvb including the IE header and data as ieee802154_packet
3971 */
3972
3973 /**
3974 * Dissect the CSL IE (7.4.2.3)
3975 */
3976 static int
dissect_hie_csl(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)3977 dissect_hie_csl(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
3978 {
3979 proto_tree *subtree = ieee802154_create_hie_tree(tvb, tree, hf_ieee802154_hie_csl, ett_ieee802154_hie_csl);
3980 proto_tree_add_item(subtree, hf_ieee802154_hie_csl_phase, tvb, 2, 2, ENC_LITTLE_ENDIAN);
3981 proto_tree_add_item(subtree, hf_ieee802154_hie_csl_period, tvb, 4, 2, ENC_LITTLE_ENDIAN);
3982 if (tvb_reported_length(tvb) >= 8) {
3983 proto_tree_add_item(subtree, hf_ieee802154_hie_csl_rendezvous_time, tvb, 6, 2, ENC_LITTLE_ENDIAN);
3984 return 2 + 6;
3985 }
3986 return 2 + 4;
3987 }
3988
3989 /**
3990 * Dissect the Time Correction Header IE (7.4.2.7)
3991 *
3992 * This field is constructed by taking a signed 16-bit 2's compliment time
3993 * correction in the range of -2048 us to 2047 us, AND'ing it with 0xfff, and
3994 * OR'ing again with 0x8000 to indicate a negative acknowledgment.
3995 */
3996 static int
dissect_hie_time_correction(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * ies_tree,void * data _U_)3997 dissect_hie_time_correction(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *ies_tree, void *data _U_)
3998 {
3999 static int * const fields[] = {
4000 &hf_ieee802154_hie_time_correction_value,
4001 &hf_ieee802154_nack,
4002 NULL
4003 };
4004 proto_tree *tree = ieee802154_create_hie_tree(tvb, ies_tree, hf_ieee802154_hie_time_correction, ett_ieee802154_hie_time_correction);
4005 guint16 time_sync_value = tvb_get_letohs(tvb, 2);
4006 proto_tree_add_bitmask_with_flags(tree, tvb, 2, hf_ieee802154_hie_time_correction_time_sync_info, ett_ieee802154_header_ie,
4007 fields, ENC_LITTLE_ENDIAN, BMT_NO_FLAGS);
4008
4009 if (time_sync_value & ~(0x8fff)) {
4010 expert_add_info(pinfo, proto_tree_get_parent(tree), &ei_ieee802154_time_correction_error);
4011 }
4012 if (time_sync_value & 0x8000) {
4013 proto_item_append_text(proto_tree_get_parent(ies_tree), ": NACK");
4014 }
4015 return 2 + 2;
4016 }
4017
4018 static int
dissect_hie_global_time(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)4019 dissect_hie_global_time(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
4020 {
4021 proto_tree *subtree = ieee802154_create_hie_tree(tvb, tree, hf_ieee802154_hie_global_time, ett_ieee802154_hie_global_time);
4022 proto_tree_add_item(subtree, hf_ieee802154_hie_global_time_value, tvb, 2, 4, ENC_TIME_SECS|ENC_LITTLE_ENDIAN);
4023 return 2 + 4;
4024 }
4025
4026 /**
4027 * Dissect the Vendor Specific IE (7.4.2.2)
4028 */
4029 static int
dissect_hie_vendor_specific(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)4030 dissect_hie_vendor_specific(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
4031 {
4032 proto_tree *subtree = ieee802154_create_hie_tree(tvb, tree, hf_ieee802154_hie_vendor_specific,
4033 ett_ieee802154_hie_vendor_specific);
4034
4035 guint hie_length = tvb_reported_length(tvb) - 2;
4036 guint offset = 2;
4037
4038 tvb_get_letoh24(tvb, offset);
4039 proto_tree_add_item(subtree, hf_ieee802154_hie_vendor_specific_vendor_oui, tvb, offset, 3, ENC_LITTLE_ENDIAN);
4040 offset += 3; /* adjust for vendor OUI */
4041 hie_length -= 3;
4042
4043 proto_tree_add_item(subtree, hf_ieee802154_hie_vendor_specific_content, tvb, offset, hie_length, ENC_NA);
4044
4045 return tvb_reported_length(tvb);
4046 }
4047
4048 /**
4049 * Subdissector for Header IEs (Information Elements)
4050 *
4051 * Since the header is never encrypted and the payload may be encrypted,
4052 * we dissect header and payload IEs separately.
4053 * The termination of the Header IE tells us whether there are any
4054 * payload IEs to follow.
4055 *
4056 * @param tvb the tv buffer
4057 * @param pinfo pointer to packet information fields.
4058 * @param tree the tree to append this item to
4059 * @param orig_offset offset into the tvbuff to begin dissection.
4060 * @param packet IEEE 802.15.4 packet information.
4061 */
4062 static int
dissect_ieee802154_header_ie(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint orig_offset,ieee802154_packet * packet)4063 dissect_ieee802154_header_ie(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint orig_offset, ieee802154_packet *packet)
4064 {
4065 // GCC emits a spurious -Wclobbered if offset is used as function parameter (even with volatile)
4066 volatile guint offset = orig_offset;
4067 proto_item *ies_item = proto_tree_add_item(tree, hf_ieee802154_header_ies, tvb, offset, -1, ENC_NA);
4068 proto_tree *ies_tree = proto_item_add_subtree(ies_item, ett_ieee802154_header_ie);
4069 volatile gint remaining = tvb_reported_length_remaining(tvb, offset) - IEEE802154_MIC_LENGTH(packet->security_level);
4070
4071 // Loop as long as we don't:
4072 //
4073 // 1) run out of data;
4074 // 2) get a header termination IE.
4075 //
4076 // See Table 9-6 "Termination IE inclusion rules" of IEEE Std 802.15.4-2015;
4077 // unless we have no payload IEs and no payload data, we *have* to have
4078 // a header termination IE to end the list of header IEs, so the "run out
4079 // of data" check needs only to check whether there's any data
4080 // left in the tvbuff (which has already had the FCS removed from
4081 // it), other than a MIC if present - if we have no payload IEs or
4082 // payload data, there might still be a MIC to Check the Message
4083 // Integrity.
4084 //
4085 // XXX - we should make sure we have enough data left for an IE header,
4086 // and report a malformed frame if not, and if we do have enough data,
4087 // make sure we have enough data for the full IE, and report a malformed
4088 // frame if not.
4089 do {
4090 volatile int consumed = 0;
4091 guint16 ie_header = tvb_get_letohs(tvb, offset);
4092 guint16 id = (guint16) ((ie_header & IEEE802154_HEADER_IE_ID_MASK) >> 7);
4093 guint16 length = (guint16) (ie_header & IEEE802154_HEADER_IE_LENGTH_MASK);
4094 tvbuff_t *ie_tvb = tvb_new_subset_length(tvb, offset, 2 + length);
4095
4096 if (id == IEEE802154_HEADER_IE_HT1 || id == IEEE802154_HEADER_IE_HT2) {
4097 int hf_term_ie = (id == IEEE802154_HEADER_IE_HT1) ? hf_ieee802154_hie_ht1 : hf_ieee802154_hie_ht2;
4098 ieee802154_create_hie_tree(ie_tvb, ies_tree, hf_term_ie, ett_ieee802154_hie_ht);
4099 consumed = 2;
4100 } else {
4101 TRY {
4102 consumed = dissector_try_uint_new(header_ie_dissector_table, id, ie_tvb, pinfo, ies_tree, FALSE, packet);
4103 if (consumed == 0) {
4104 proto_tree *subtree = ieee802154_create_hie_tree(ie_tvb, ies_tree, hf_ieee802154_hie_unsupported,
4105 ett_ieee802154_hie_unsupported);
4106 proto_tree_add_item(subtree, hf_ieee802154_ie_unknown_content, ie_tvb, 2, length, ENC_NA);
4107 consumed = 2 + length;
4108 if (ie_header & IEEE802154_PAYLOAD_IE_TYPE_MASK) {
4109 expert_add_info(pinfo, ies_tree, &ei_ieee802154_payload_ie_in_header);
4110 } else {
4111 expert_add_info(pinfo, ies_tree, &ei_ieee802154_ie_unsupported_id);
4112 }
4113 }
4114 }
4115 CATCH_ALL {
4116 show_exception(tvb, pinfo, ies_tree, EXCEPT_CODE, GET_MESSAGE);
4117 consumed = 2 + length;
4118 }
4119 ENDTRY;
4120 }
4121
4122 if (consumed < 2 + length) {
4123 proto_tree_add_item(ies_tree, hf_ieee802154_ie_unknown_content, ie_tvb, consumed, 2 + length - consumed, ENC_NA);
4124 expert_add_info(pinfo, ies_item, &ei_ieee802154_ie_unknown_extra_content);
4125 }
4126
4127 offset += 2 + length;
4128 remaining -= 2 + length;
4129
4130 if (id == IEEE802154_HEADER_IE_HT1 || id == IEEE802154_HEADER_IE_HT2) {
4131 packet->payload_ie_present = (id == IEEE802154_HEADER_IE_HT1);
4132 break;
4133 }
4134 } while (remaining > 0);
4135
4136 proto_item_set_len(ies_item, offset - orig_offset);
4137 return offset - orig_offset;
4138 }
4139
4140 static int
dissect_802154_eb_filter(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)4141 dissect_802154_eb_filter(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
4142 {
4143 guint8 filter;
4144 guint8 attr_len;
4145 proto_tree *subtree;
4146 guint offset = 0;
4147
4148 static int * const fields_eb_filter[] = {
4149 &hf_ieee802154_psie_eb_filter_pjoin,
4150 &hf_ieee802154_psie_eb_filter_lqi,
4151 &hf_ieee802154_psie_eb_filter_percent,
4152 &hf_ieee802154_psie_eb_filter_attr_id,
4153 /* reserved 5-7 */
4154 NULL
4155 };
4156
4157 subtree = ieee802154_create_psie_tree(tvb, tree, hf_ieee802154_psie_eb_filter, ett_ieee802154_eb_filter);
4158 offset += 2;
4159
4160 filter = tvb_get_guint8(tvb, offset);
4161 proto_tree_add_bitmask(subtree, tvb, offset, hf_ieee802154_psie_eb_filter,
4162 ett_ieee802154_eb_filter_bitmap, fields_eb_filter, ENC_NA);
4163 offset++;
4164
4165 if (filter & IEEE802154_MLME_PSIE_EB_FLT_LQI) {
4166 proto_tree_add_item(subtree, hf_ieee802154_psie_eb_filter_lqi_min, tvb, offset, 1, ENC_NA);
4167 offset++;
4168 }
4169
4170 if (filter & IEEE802154_MLME_PSIE_EB_FLT_PERCENT) {
4171 proto_tree_add_item(subtree, hf_ieee802154_psie_eb_filter_percent_prob, tvb, offset, 1, ENC_NA);
4172 offset++;
4173 }
4174
4175 attr_len = (guint8) ((filter & IEEE802154_MLME_PSIE_EB_FLT_ATTR_LEN) >> 3);
4176 if (attr_len) {
4177 /* just display in hex until we know how to decode */
4178 proto_tree_add_item(subtree, hf_ieee802154_psie_eb_filter_attr_id_bitmap, tvb, offset, attr_len, ENC_LITTLE_ENDIAN);
4179 offset += attr_len;
4180 }
4181
4182 return offset;
4183 }
4184
4185 /**
4186 * Subdissector for MLME IEs
4187 */
4188 static int
dissect_pie_mlme(tvbuff_t * tvb,packet_info * pinfo,proto_tree * ies_tree,void * data)4189 dissect_pie_mlme(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ies_tree, void *data)
4190 {
4191 proto_tree *tree = ieee802154_create_pie_tree(tvb, ies_tree, hf_ieee802154_mlme, ett_ieee802154_mlme);
4192 volatile guint offset = 2;
4193
4194 while (tvb_reported_length_remaining(tvb, offset) > 1) {
4195 guint16 psie_ie = tvb_get_letohs(tvb, offset);
4196 volatile guint16 psie_id;
4197 tvbuff_t *volatile psie_tvb;
4198
4199 if (psie_ie & IEEE802154_PSIE_TYPE_MASK) {
4200 /* long format: Table 7-17-Sub-ID allocation for long format */
4201 psie_id = (guint16) ((psie_ie & IEEE802154_PSIE_ID_MASK_LONG) >> 11);
4202 psie_tvb = tvb_new_subset_length(tvb, offset, (psie_ie & IEEE802154_PSIE_LENGTH_MASK_LONG) + 2);
4203 }
4204 else {
4205 /* short format: Table 7-16-Sub-ID allocation for short format */
4206 psie_id = (guint16) ((psie_ie & IEEE802154_PSIE_ID_MASK_SHORT) >> 8);
4207 psie_tvb = tvb_new_subset_length(tvb, offset, (psie_ie & IEEE802154_PSIE_LENGTH_MASK_SHORT) + 2);
4208 }
4209 offset += tvb_reported_length(psie_tvb);
4210
4211 /* Pass the tvb off to a subdissector. */
4212 TRY {
4213 guint consumed = dissector_try_uint_new(mlme_ie_dissector_table, psie_id, psie_tvb, pinfo, tree, FALSE, data);
4214 if (consumed == 0) {
4215 proto_tree *subtree = ieee802154_create_psie_tree(psie_tvb, tree, hf_ieee802154_mlme_ie_unsupported, ett_ieee802154_mlme_unsupported);
4216 if (tvb_reported_length(psie_tvb) > 2) {
4217 proto_tree_add_item(subtree, hf_ieee802154_mlme_ie_data, psie_tvb, 2, -1, ENC_NA);
4218 }
4219 expert_add_info(pinfo, subtree, &ei_ieee802154_ie_unsupported_id);
4220 }
4221 }
4222 CATCH_ALL {
4223 show_exception(tvb, pinfo, ies_tree, EXCEPT_CODE, GET_MESSAGE);
4224 }
4225 ENDTRY;
4226 }
4227 return offset;
4228 }
4229
4230 /**
4231 * Subdissector for MPX IEs (IEEE 802.15.9)
4232 */
4233 static int
dissect_mpx_ie(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * ies_tree,void * data _U_)4234 dissect_mpx_ie(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *ies_tree, void *data _U_)
4235 {
4236 static int * const fields[] = {
4237 &hf_ieee802159_mpx_transaction_id,
4238 &hf_ieee802159_mpx_transfer_type,
4239 NULL
4240 };
4241 static int * const fields_compressed_multiplex_id[] = {
4242 &hf_ieee802159_mpx_transaction_id_as_multiplex_id,
4243 &hf_ieee802159_mpx_transfer_type,
4244 NULL
4245 };
4246
4247 proto_tree *tree = ieee802154_create_pie_tree(tvb, ies_tree, hf_ieee802159_mpx, ett_ieee802159_mpx);
4248 guint offset = 2;
4249 guint8 transaction_control = tvb_get_guint8(tvb, offset);
4250 guint8 transfer_type = (guint8) (transaction_control & IEEE802159_MPX_TRANSFER_TYPE_MASK);
4251 guint8 transaction_id = (guint8) ((transaction_control & IEEE802159_MPX_TRANSACTION_ID_MASK) >> IEEE802159_MPX_TRANSACTION_ID_SHIFT);
4252 gint32 multiplex_id = -1;
4253 guint8 fragment_number;
4254
4255 if (transfer_type == IEEE802159_MPX_FULL_FRAME_NO_MUXID) {
4256 proto_tree_add_bitmask_with_flags(tree, tvb, offset, hf_ieee802159_mpx_transaction_control, ett_ieee802159_mpx_transaction_control,
4257 fields_compressed_multiplex_id, ENC_LITTLE_ENDIAN, BMT_NO_FLAGS);
4258 multiplex_id = transaction_id;
4259 } else {
4260 proto_tree_add_bitmask_with_flags(tree, tvb, offset, hf_ieee802159_mpx_transaction_control, ett_ieee802159_mpx_transaction_control,
4261 fields, ENC_LITTLE_ENDIAN, BMT_NO_FLAGS);
4262 }
4263 offset += 1;
4264
4265 switch (transfer_type) { // cf. IEEE 802.15.9 Table 18 - Summary of different MPX IE formats
4266 case IEEE802159_MPX_FULL_FRAME:
4267 multiplex_id = tvb_get_letohs(tvb, offset);
4268 proto_tree_add_uint_format_value(tree, hf_ieee802159_mpx_multiplex_id, tvb, offset, 2, multiplex_id, "%s (0x%04x)",
4269 val_to_str_const(multiplex_id, (multiplex_id > 1500) ? etype_vals : mpx_multiplex_id_vals, "Unknown"), multiplex_id);
4270 offset += 2;
4271 break;
4272 case IEEE802159_MPX_FULL_FRAME_NO_MUXID:
4273 break; // nothing to do
4274 case IEEE802159_MPX_NON_LAST_FRAGMENT:
4275 fragment_number = tvb_get_guint8(tvb, offset);
4276 proto_tree_add_item(tree, hf_ieee802159_mpx_fragment_number, tvb, offset, 1, ENC_LITTLE_ENDIAN);
4277 offset += 1;
4278 if (fragment_number == 0) {
4279 proto_tree_add_item(tree, hf_ieee802159_mpx_total_frame_size, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4280 offset += 2;
4281 multiplex_id = tvb_get_letohs(tvb, offset);
4282 proto_tree_add_item(tree, hf_ieee802159_mpx_multiplex_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4283 offset += 2;
4284 }
4285 break;
4286 case IEEE802159_MPX_LAST_FRAGMENT:
4287 proto_tree_add_item(tree, hf_ieee802159_mpx_fragment_number, tvb, offset, 1, ENC_LITTLE_ENDIAN);
4288 offset += 1;
4289 break;
4290 case IEEE802159_MPX_ABORT:
4291 if (tvb_reported_length_remaining(tvb, offset) == 2) {
4292 proto_tree_add_item(tree, hf_ieee802159_mpx_total_frame_size, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4293 offset += 2;
4294 }
4295 return offset;
4296 default: // reserved values -> warning and return
4297 expert_add_info(pinfo, proto_tree_get_parent(tree), &ei_ieee802159_mpx_invalid_transfer_type);
4298 return offset;
4299 }
4300
4301 // TODO: reassembly
4302
4303 dissector_handle_t dissector = NULL;
4304
4305 if (multiplex_id == IEEE802159_MPX_MULTIPLEX_ID_KMP) {
4306 guint8 kmp_id = tvb_get_guint8(tvb, offset);
4307 proto_tree_add_item(tree, hf_ieee802159_mpx_kmp_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
4308 offset += 1;
4309 switch (kmp_id) {
4310 case IEEE802159_MPX_KMP_ID_IEEE8021X:
4311 case IEEE802159_MPX_KMP_ID_IEEE80211_4WH:
4312 case IEEE802159_MPX_KMP_ID_IEEE80211_GKH:
4313 dissector = eapol_handle;
4314 break;
4315
4316 // TODO
4317 case IEEE802159_MPX_KMP_ID_HIP:
4318 case IEEE802159_MPX_KMP_ID_IKEV2:
4319 case IEEE802159_MPX_KMP_ID_PANA:
4320 case IEEE802159_MPX_KMP_ID_DRAGONFLY:
4321 case IEEE802159_MPX_KMP_ID_ETSI_TS_102_887_2:
4322 expert_add_info(pinfo, proto_tree_get_parent(tree), &ei_ieee802159_mpx_unsupported_kmp);
4323 break;
4324
4325 case IEEE802159_MPX_KMP_ID_VENDOR_SPECIFIC:
4326 proto_tree_add_item(tree, hf_ieee802159_mpx_kmp_vendor_oui, tvb, offset, 3, ENC_BIG_ENDIAN);
4327 offset += 3;
4328 break;
4329
4330 // Unknown
4331 default:
4332 expert_add_info(pinfo, proto_tree_get_parent(tree), &ei_ieee802159_mpx_unknown_kmp);
4333 }
4334 }
4335 else if (multiplex_id == IEEE802159_MPX_MULTIPLEX_ID_WISUN) {
4336 guint8 subid = tvb_get_guint8(tvb, offset);
4337 proto_tree_add_item(tree, hf_ieee802159_mpx_wisun_subid, tvb, offset, 1, ENC_LITTLE_ENDIAN);
4338 offset += 1;
4339 switch (subid) {
4340 case IEEE802159_MPX_WISUN_SUBID_6LOWPAN:
4341 dissector = lowpan_handle;
4342 break;
4343
4344 case IEEE802159_MPX_WISUN_SUBID_SECURITY:
4345 dissector = wisun_sec_handle;
4346 break;
4347
4348 case IEEE802159_MPX_WISUN_SUBID_MHDS:
4349 expert_add_info(pinfo, proto_tree_get_parent(tree), &ei_ieee802159_mpx_unsupported_kmp);
4350 break;
4351
4352 default:
4353 expert_add_info(pinfo, proto_tree_get_parent(tree), &ei_ieee802159_mpx_unknown_kmp);
4354 break;
4355 }
4356 }
4357 else if (multiplex_id > 1500) {
4358 dissector = dissector_get_uint_handle(ethertype_table, (guint)multiplex_id);
4359 }
4360
4361 if (transfer_type == IEEE802159_MPX_FULL_FRAME || transfer_type == IEEE802159_MPX_FULL_FRAME_NO_MUXID) {
4362 tvbuff_t * payload = tvb_new_subset_remaining(tvb, offset);
4363 if (dissector) {
4364 call_dissector(dissector, payload, pinfo, proto_tree_get_root(tree)); // exceptions are caught in our caller
4365 } else {
4366 call_data_dissector(payload, pinfo, proto_tree_get_root(tree));
4367 }
4368 } else {
4369 proto_tree_add_item(tree, hf_ieee802159_mpx_fragment, tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_NA);
4370 }
4371 offset = tvb_reported_length(tvb);
4372
4373 return offset;
4374 }
4375
4376 /**
4377 * Subdissector for Vendor Specific Payload IEs (Information Elements)
4378 */
4379 static int
dissect_pie_vendor(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * ies_tree,void * data _U_)4380 dissect_pie_vendor(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *ies_tree, void *data _U_)
4381 {
4382 proto_tree *tree = ieee802154_create_pie_tree(tvb, ies_tree, hf_ieee802154_pie_vendor, ett_ieee802154_pie_vendor);
4383
4384 guint offset = 2;
4385 guint pie_length = tvb_reported_length(tvb) - 2;
4386 tvbuff_t *next_tvb;
4387 guint32 vendor_oui;
4388
4389 vendor_oui = tvb_get_letoh24(tvb, offset);
4390 proto_tree_add_item(tree, hf_ieee802154_pie_vendor_oui, tvb, offset, 3, ENC_LITTLE_ENDIAN);
4391 offset += 3; /* adjust for vendor OUI */
4392 pie_length -= 3;
4393 next_tvb = tvb_new_subset_length(tvb, offset, pie_length);
4394
4395 switch (vendor_oui) {
4396 case OUI_ZIGBEE:
4397 call_dissector_with_data(zigbee_ie_handle, next_tvb, pinfo, tree, &pie_length);
4398 break;
4399
4400 default:
4401 call_data_dissector(next_tvb, pinfo, tree);
4402 break;
4403 }
4404
4405 return tvb_reported_length(tvb);
4406 }
4407
4408 /**
4409 * Subdissector for Payload IEs (Information Elements)
4410 *
4411 * @param tvb the tv buffer
4412 * @param pinfo pointer to packet information fields.
4413 * @param tree the tree to append this item to
4414 * @param orig_offset offset into the tvbuff to begin dissection.
4415 * @param packet IEEE 802.15.4 packet information.
4416 */
4417 static int
dissect_ieee802154_payload_ie(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,guint orig_offset,ieee802154_packet * packet)4418 dissect_ieee802154_payload_ie(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint orig_offset, ieee802154_packet *packet)
4419 {
4420 // GCC emits a spurious -Wclobbered if offset is used as function parameter (even with volatile)
4421 volatile guint offset = orig_offset;
4422 proto_item *ies_item = proto_tree_add_item(tree, hf_ieee802154_payload_ies, tvb, offset, -1, ENC_NA);
4423 proto_tree *ies_tree = proto_item_add_subtree(ies_item, ett_ieee802154_payload_ie);
4424
4425 do {
4426 volatile int consumed = 0;
4427 guint16 ie_header = tvb_get_letohs(tvb, offset);
4428 guint16 id = (guint16) ((ie_header & IEEE802154_PAYLOAD_IE_ID_MASK) >> 11);
4429 volatile guint16 length = (guint16) (ie_header & IEEE802154_PAYLOAD_IE_LENGTH_MASK);
4430 tvbuff_t *ie_tvb = tvb_new_subset_length(tvb, offset, 2 + length);
4431
4432 if (id == IEEE802154_PAYLOAD_IE_TERMINATION) {
4433 ieee802154_create_pie_tree(ie_tvb, ies_tree, hf_ieee802154_pie_termination, ett_ieee802154_pie_termination);
4434 consumed = 2;
4435 } else {
4436 TRY {
4437 consumed = dissector_try_uint_new(payload_ie_dissector_table, id, ie_tvb, pinfo, ies_tree, FALSE, packet);
4438 if (consumed == 0) {
4439 proto_tree *subtree = ieee802154_create_pie_tree(ie_tvb, ies_tree, hf_ieee802154_pie_unsupported,
4440 ett_ieee802154_pie_unsupported);
4441 proto_tree_add_item(subtree, hf_ieee802154_ie_unknown_content, ie_tvb, 2, length, ENC_NA);
4442 consumed = 2 + length;
4443 expert_add_info(pinfo, proto_tree_get_parent(subtree), &ei_ieee802154_ie_unsupported_id);
4444 }
4445 }
4446 CATCH_ALL {
4447 show_exception(tvb, pinfo, ies_tree, EXCEPT_CODE, GET_MESSAGE);
4448 consumed = 2 + length;
4449 }
4450 ENDTRY;
4451 }
4452
4453 if (consumed < 2 + length) {
4454 proto_tree_add_item(ies_tree, hf_ieee802154_ie_unknown_content, ie_tvb, consumed, 2 + length - consumed, ENC_NA);
4455 expert_add_info(pinfo, ies_item, &ei_ieee802154_ie_unknown_extra_content);
4456 }
4457
4458 offset += 2 + length;
4459
4460 if (id == IEEE802154_PAYLOAD_IE_TERMINATION) {
4461 break;
4462 }
4463 } while (tvb_reported_length_remaining(tvb, offset) > 1);
4464
4465 proto_item_set_len(ies_item, offset - orig_offset);
4466 return offset - orig_offset;
4467 }
4468
4469 static const true_false_string tfs_cinfo_device_type = { "FFD", "RFD" };
4470 static const true_false_string tfs_cinfo_power_src = { "AC/Mains Power", "Battery" };
4471
4472 /**
4473 * Command subdissector routine for the Association request command.
4474 *
4475 * @param tvb pointer to buffer containing raw packet.
4476 * @param pinfo pointer to packet information fields.
4477 * @param tree pointer to protocol tree.
4478 * @param packet IEEE 802.15.4 packet information.
4479 */
4480
4481 static void
dissect_ieee802154_assoc_req(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,ieee802154_packet * packet)4482 dissect_ieee802154_assoc_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
4483 {
4484 guint8 cap;
4485 proto_tree *subtree;
4486 static int * const capability[] = {
4487 &hf_ieee802154_cinfo_alt_coord,
4488 &hf_ieee802154_cinfo_device_type,
4489 &hf_ieee802154_cinfo_power_src,
4490 &hf_ieee802154_cinfo_idle_rx,
4491 &hf_ieee802154_cinfo_sec_capable,
4492 &hf_ieee802154_cinfo_alloc_addr,
4493 NULL
4494 };
4495
4496 cap = tvb_get_guint8(tvb, 0);
4497 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", tfs_get_string(cap & IEEE802154_CMD_CINFO_DEVICE_TYPE, &tfs_cinfo_device_type));
4498
4499 /* Create a subtree for this command frame. */
4500 subtree = proto_tree_add_subtree(tree, tvb, 0, 1, ett_ieee802154_cmd, NULL,
4501 val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
4502
4503 /* Get and display capability info. */
4504 proto_tree_add_bitmask_list(subtree, tvb, 0, 1, capability, ENC_NA);
4505
4506 /* Call the data dissector for any leftover bytes. */
4507 if (tvb_reported_length(tvb) > 1) {
4508 call_data_dissector(tvb_new_subset_remaining(tvb, 1), pinfo, tree);
4509 }
4510 } /* dissect_ieee802154_assoc_req */
4511
4512 /**
4513 * Command subdissector routine for the Association response command.
4514 *
4515 * @param tvb pointer to buffer containing raw packet.
4516 * @param pinfo pointer to packet information fields.
4517 * @param tree pointer to protocol tree.
4518 * @param packet IEEE 802.15.4 packet information.
4519 */
4520 static void
dissect_ieee802154_assoc_rsp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,ieee802154_packet * packet)4521 dissect_ieee802154_assoc_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
4522 {
4523 proto_tree *subtree;
4524 proto_item *ti;
4525 guint16 short_addr;
4526 guint8 status;
4527 guint offset = 0;
4528
4529 /* Create a subtree for this command frame. */
4530 subtree = proto_tree_add_subtree(tree, tvb, offset, 3, ett_ieee802154_cmd, NULL,
4531 val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
4532
4533 /* Get and display the short address. */
4534 short_addr = tvb_get_letohs(tvb, offset);
4535 proto_tree_add_uint(subtree, hf_ieee802154_assoc_addr, tvb, offset, 2, short_addr);
4536 offset += 2;
4537
4538 /* Get and display the status. */
4539 status = tvb_get_guint8(tvb, offset);
4540 if (tree) {
4541 ti = proto_tree_add_uint(subtree, hf_ieee802154_assoc_status, tvb, offset, 1, status);
4542 if (status == IEEE802154_CMD_ASRSP_AS_SUCCESS) proto_item_append_text(ti, " (Association Successful)");
4543 else if (status == IEEE802154_CMD_ASRSP_PAN_FULL) proto_item_append_text(ti, " (PAN Full)");
4544 else if (status == IEEE802154_CMD_ASRSP_PAN_DENIED) proto_item_append_text(ti, " (Association Denied)");
4545 else proto_item_append_text(ti, " (Reserved)");
4546 }
4547 offset += 1;
4548
4549 /* Update the info column. */
4550 if (status == IEEE802154_CMD_ASRSP_AS_SUCCESS) {
4551 /* Association was successful. */
4552 if (packet->src_addr_mode != IEEE802154_FCF_ADDR_SHORT) {
4553 col_append_fstr(pinfo->cinfo, COL_INFO, ", PAN: 0x%04x", packet->dst_pan);
4554 }
4555 if (short_addr != IEEE802154_NO_ADDR16) {
4556 col_append_fstr(pinfo->cinfo, COL_INFO, " Addr: 0x%04x", short_addr);
4557 }
4558 }
4559 else {
4560 /* Association was unsuccessful. */
4561 col_append_str(pinfo->cinfo, COL_INFO, ", Unsuccessful");
4562 }
4563
4564 /* Update the address table. */
4565 if ((status == IEEE802154_CMD_ASRSP_AS_SUCCESS) && (short_addr != IEEE802154_NO_ADDR16)) {
4566 ieee802154_addr_update(&ieee802154_map, short_addr, packet->dst_pan, packet->dst64,
4567 pinfo->current_proto, pinfo->num);
4568 }
4569
4570 /* Call the data dissector for any leftover bytes. */
4571 if (tvb_captured_length(tvb) > offset) {
4572 call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, tree);
4573 }
4574 } /* dissect_ieee802154_assoc_rsp */
4575
4576 /**
4577 * Command subdissector routine for the Disassociate command.
4578 *
4579 * @param tvb pointer to buffer containing raw packet.
4580 * @param pinfo pointer to packet information fields.
4581 * @param tree pointer to protocol tree.
4582 * @param packet IEEE 802.15.4 packet information.
4583 */
4584 static void
dissect_ieee802154_disassoc(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,ieee802154_packet * packet)4585 dissect_ieee802154_disassoc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
4586 {
4587 proto_tree *subtree;
4588 proto_item *ti;
4589 guint8 reason;
4590
4591 /* Create a subtree for this command frame. */
4592 subtree = proto_tree_add_subtree(tree, tvb, 0, 1, ett_ieee802154_cmd, NULL,
4593 val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
4594
4595 /* Get and display the disassociation reason. */
4596 reason = tvb_get_guint8(tvb, 0);
4597 if (tree) {
4598 ti = proto_tree_add_uint(subtree, hf_ieee802154_disassoc_reason, tvb, 0, 1, reason);
4599 switch (reason) {
4600 case 0x01:
4601 proto_item_append_text(ti, " (Coordinator requests device to leave)");
4602 break;
4603
4604 case 0x02:
4605 proto_item_append_text(ti, " (Device wishes to leave)");
4606 break;
4607
4608 default:
4609 proto_item_append_text(ti, " (Reserved)");
4610 break;
4611 } /* switch */
4612 }
4613
4614 if (!PINFO_FD_VISITED(pinfo)) {
4615 /* Update the address tables */
4616 if ( packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT ) {
4617 ieee802154_long_addr_invalidate(packet->dst64, pinfo->num);
4618 } else if ( packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT ) {
4619 ieee802154_short_addr_invalidate(packet->dst16, packet->dst_pan, pinfo->num);
4620 }
4621 }
4622
4623 /* Call the data dissector for any leftover bytes. */
4624 if (tvb_captured_length(tvb) > 1) {
4625 call_data_dissector(tvb_new_subset_remaining(tvb, 1), pinfo, tree);
4626 }
4627 } /* dissect_ieee802154_disassoc */
4628
4629 /**
4630 * Command subdissector routine for the Coordinator Realignment command.
4631 *
4632 * @param tvb pointer to buffer containing raw packet.
4633 * @param pinfo pointer to packet information fields.
4634 * @param tree pointer to protocol tree.
4635 * @param packet IEEE 802.15.4 packet information.
4636 */
4637 static void
dissect_ieee802154_realign(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,ieee802154_packet * packet)4638 dissect_ieee802154_realign(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
4639 {
4640 proto_tree *subtree;
4641 proto_item *subitem;
4642 guint16 pan_id;
4643 guint16 coord_addr;
4644 guint8 channel;
4645 guint16 short_addr;
4646 guint offset = 0;
4647
4648 /* Create a subtree for this command frame. */
4649 subtree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_ieee802154_cmd, &subitem,
4650 val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
4651
4652 /* Get and display the command PAN ID. */
4653 pan_id = tvb_get_letohs(tvb, offset);
4654 proto_tree_add_uint(subtree, hf_ieee802154_realign_pan, tvb, offset, 2, pan_id);
4655 col_append_fstr(pinfo->cinfo, COL_INFO, ", PAN: 0x%04x", pan_id);
4656 offset += 2;
4657
4658 /* Get and display the coordinator address. */
4659 coord_addr = tvb_get_letohs(tvb, offset);
4660 proto_tree_add_uint(subtree, hf_ieee802154_realign_caddr, tvb, offset, 2, coord_addr);
4661 col_append_fstr(pinfo->cinfo, COL_INFO, ", Coordinator: 0x%04x", coord_addr);
4662 offset += 2;
4663
4664 /* Get and display the channel. */
4665 channel = tvb_get_guint8(tvb, offset);
4666 proto_tree_add_uint(subtree, hf_ieee802154_realign_channel, tvb, offset, 1, channel);
4667 col_append_fstr(pinfo->cinfo, COL_INFO, ", Channel: %u", channel);
4668 offset += 1;
4669
4670 /* Get and display the short address. */
4671 short_addr = tvb_get_letohs(tvb, offset);
4672 if (tree) proto_tree_add_uint(subtree, hf_ieee802154_realign_addr, tvb, offset, 2, short_addr);
4673 if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT)
4674 && (short_addr != IEEE802154_NO_ADDR16)) {
4675 col_append_fstr(pinfo->cinfo, COL_INFO, ", Addr: 0x%04x", short_addr);
4676 }
4677 offset += 2;
4678 /* Update the address table. */
4679 if ((short_addr != IEEE802154_NO_ADDR16) && (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT)) {
4680 ieee802154_addr_update(&ieee802154_map, short_addr, packet->dst_pan, packet->dst64,
4681 pinfo->current_proto, pinfo->num);
4682 }
4683
4684 /* Get and display the channel page, if it exists. Added in IEEE802.15.4-2006 */
4685 if (tvb_bytes_exist(tvb, offset, 1)) {
4686 guint8 channel_page = tvb_get_guint8(tvb, offset);
4687 if (tree) proto_tree_add_uint(subtree, hf_ieee802154_realign_channel_page, tvb, offset, 1, channel_page);
4688 offset += 1;
4689 }
4690
4691 /* Fix the length of the command subtree. */
4692 if (tree) {
4693 proto_item_set_len(subitem, offset);
4694 }
4695
4696 /* Call the data dissector for any leftover bytes. */
4697 if (tvb_captured_length(tvb) > offset) {
4698 call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, tree);
4699 }
4700 } /* dissect_ieee802154_realign */
4701
4702 static const true_false_string tfs_gtsreq_dir = { "Receive", "Transmit" };
4703 static const true_false_string tfs_gtsreq_type= { "Allocate GTS", "Deallocate GTS" };
4704
4705 /**
4706 * Command subdissector routine for the GTS request command.
4707 *
4708 * Assumes that COL_INFO will be set to the command name,
4709 * command name will already be appended to the command subtree
4710 * and protocol root. In addition, assumes that the command ID
4711 * has already been parsed.
4712 *
4713 * @param tvb pointer to buffer containing raw packet.
4714 * @param pinfo pointer to packet information fields (unused).
4715 * @param tree pointer to protocol tree.
4716 * @param packet IEEE 802.15.4 packet information (unused).
4717 */
4718
4719 static void
dissect_ieee802154_gtsreq(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,ieee802154_packet * packet)4720 dissect_ieee802154_gtsreq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
4721 {
4722 proto_tree *subtree;
4723 static int * const characteristics[] = {
4724 &hf_ieee802154_gtsreq_len,
4725 &hf_ieee802154_gtsreq_dir,
4726 &hf_ieee802154_gtsreq_type,
4727 NULL
4728 };
4729
4730 /* Create a subtree for this command frame. */
4731 subtree = proto_tree_add_subtree(tree, tvb, 0, 1, ett_ieee802154_cmd, NULL,
4732 val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
4733
4734 proto_tree_add_bitmask_list(subtree, tvb, 0, 1, characteristics, ENC_NA);
4735
4736 /* Call the data dissector for any leftover bytes. */
4737 if (tvb_reported_length(tvb) > 1) {
4738 call_data_dissector(tvb_new_subset_remaining(tvb, 1), pinfo, tree);
4739 }
4740 } /* dissect_ieee802154_gtsreq */
4741
4742 /**
4743 * Subdissector routine for IEEE 802.15.4 commands
4744 *
4745 * @param tvb pointer to buffer containing the command payload
4746 * @param pinfo pointer to packet information fields
4747 * @param tree pointer to the protocol tree
4748 * @param packet IEEE 802.15.4 packet information
4749 */
4750 static void
dissect_ieee802154_command(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,ieee802154_packet * packet)4751 dissect_ieee802154_command(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
4752 {
4753 if ((packet->version == IEEE802154_VERSION_2015) && (packet->frame_type == IEEE802154_FCF_CMD)) {
4754 /* In 802.15.4e and later the Command Id follows the Payload IEs. */
4755 packet->command_id = tvb_get_guint8(tvb, 0);
4756 proto_tree_add_uint(tree, hf_ieee802154_cmd_id, tvb, 0, 1, packet->command_id);
4757 tvb = tvb_new_subset_remaining(tvb, 1);
4758
4759 /* Display the command identifier in the info column. */
4760 if ((packet->version == IEEE802154_VERSION_2015) && (packet->command_id == IEEE802154_CMD_BEACON_REQ)) {
4761 col_set_str(pinfo->cinfo, COL_INFO, "Enhanced Beacon Request");
4762 }
4763 else {
4764 col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
4765 }
4766 }
4767
4768 switch (packet->command_id) {
4769 case IEEE802154_CMD_ASSOC_REQ:
4770 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
4771 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
4772 (packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE));
4773 dissect_ieee802154_assoc_req(tvb, pinfo, tree, packet);
4774 break;
4775
4776 case IEEE802154_CMD_ASSOC_RSP:
4777 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
4778 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
4779 (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT));
4780 dissect_ieee802154_assoc_rsp(tvb, pinfo, tree, packet);
4781 break;
4782
4783 case IEEE802154_CMD_DISASSOC_NOTIFY:
4784 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
4785 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
4786 (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT));
4787 dissect_ieee802154_disassoc(tvb, pinfo, tree, packet);
4788 break;
4789
4790 case IEEE802154_CMD_DATA_RQ:
4791 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id, packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE);
4792 /* No payload expected. */
4793 break;
4794
4795 case IEEE802154_CMD_PANID_CONFLICT:
4796 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
4797 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
4798 (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT));
4799 /* No payload expected. */
4800 break;
4801
4802 case IEEE802154_CMD_ORPHAN_NOTIFY:
4803 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
4804 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
4805 (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&
4806 (packet->dst16 == IEEE802154_BCAST_ADDR) &&
4807 (packet->src_pan == IEEE802154_BCAST_PAN) &&
4808 (packet->dst_pan == IEEE802154_BCAST_PAN));
4809 /* No payload expected. */
4810 break;
4811
4812 case IEEE802154_CMD_BEACON_REQ:
4813 if ((packet->version == IEEE802154_VERSION_2003) || (packet->version == IEEE802154_VERSION_2006)) {
4814 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
4815 (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&
4816 (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE) &&
4817 (packet->dst16 == IEEE802154_BCAST_ADDR) &&
4818 (packet->dst_pan == IEEE802154_BCAST_PAN));
4819 }
4820 /* No payload expected. */
4821 break;
4822
4823 case IEEE802154_CMD_COORD_REALIGN:
4824 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
4825 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
4826 (packet->dst_pan == IEEE802154_BCAST_PAN) &&
4827 (packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE));
4828 if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
4829 /* If directed to a 16-bit address, check that it is being broadcast. */
4830 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id, packet->dst16 == IEEE802154_BCAST_ADDR);
4831 }
4832 dissect_ieee802154_realign(tvb, pinfo, tree, packet);
4833 break;
4834
4835 case IEEE802154_CMD_GTS_REQ:
4836 /* Check that the addressing is correct for this command type. */
4837 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
4838 (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&
4839 (packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) &&
4840 (packet->src16 != IEEE802154_BCAST_ADDR) &&
4841 (packet->src16 != IEEE802154_NO_ADDR16));
4842 dissect_ieee802154_gtsreq(tvb, pinfo, tree, packet);
4843 break;
4844
4845 case IEEE802154_CMD_VENDOR_SPECIFIC:
4846 {
4847 guint32 oui = tvb_get_ntoh24(tvb, 0);
4848 if (!dissector_try_uint_new(cmd_vendor_dissector_table, oui, tvb, pinfo, tree, FALSE, packet)) {
4849 proto_tree_add_item(tree, hf_ieee802154_cmd_vendor_oui, tvb, 0, 3, ENC_BIG_ENDIAN);
4850 call_data_dissector(tvb_new_subset_remaining(tvb, 3), pinfo, tree);
4851 }
4852 break;
4853 }
4854
4855 case IEEE802154_CMD_TRLE_MGMT_REQ:
4856 case IEEE802154_CMD_TRLE_MGMT_RSP:
4857 case IEEE802154_CMD_DSME_ASSOC_REQ:
4858 case IEEE802154_CMD_DSME_ASSOC_RSP:
4859 case IEEE802154_CMD_DSME_GTS_REQ:
4860 case IEEE802154_CMD_DSME_GTS_RSP:
4861 case IEEE802154_CMD_DSME_GTS_NOTIFY:
4862 case IEEE802154_CMD_DSME_INFO_REQ:
4863 case IEEE802154_CMD_DSME_INFO_RSP:
4864 case IEEE802154_CMD_DSME_BEACON_ALLOC_NOTIFY:
4865 case IEEE802154_CMD_DSME_BEACON_COLL_NOTIFY:
4866 case IEEE802154_CMD_DSME_LINK_REPORT:
4867 case IEEE802154_CMD_RIT_DATA_REQ:
4868 case IEEE802154_CMD_DBS_REQ:
4869 case IEEE802154_CMD_DBS_RSP:
4870 case IEEE802154_CMD_RIT_DATA_RSP:
4871 /* TODO add support for these commands, for now if anything remains, dump it */
4872 expert_add_info(pinfo, tree, &ei_ieee802154_unsupported_cmd);
4873 if (tvb_captured_length_remaining(tvb, 0) > 0) {
4874 call_data_dissector(tvb, pinfo, tree);
4875 }
4876 break;
4877 default:
4878 expert_add_info(pinfo, tree, &ei_ieee802154_unknown_cmd);
4879 if (tvb_captured_length_remaining(tvb, 0) > 0) {
4880 call_data_dissector(tvb, pinfo, tree);
4881 }
4882 } /* switch */
4883 } /* dissect_ieee802154_command */
4884
4885 /**
4886 * IEEE 802.15.4 decryption algorithm
4887 * @param tvb IEEE 802.15.4 packet, not including the FCS or metadata trailer.
4888 * @param pinfo Packet info structure.
4889 * @param offset Offset where the ciphertext 'c' starts.
4890 * @param packet IEEE 802.15.4 packet information.
4891 * @return decrypted payload.
4892 */
4893 static tvbuff_t *
dissect_ieee802154_decrypt(tvbuff_t * tvb,guint offset,packet_info * pinfo,ieee802154_packet * packet,ieee802154_decrypt_info_t * decrypt_info)4894 dissect_ieee802154_decrypt(tvbuff_t *tvb,
4895 guint offset,
4896 packet_info *pinfo,
4897 ieee802154_packet *packet,
4898 ieee802154_decrypt_info_t* decrypt_info)
4899 {
4900 tvbuff_t *ptext_tvb;
4901 gboolean have_mic = FALSE;
4902 guint64 srcAddr = 0;
4903 unsigned char tmp[IEEE802154_CIPHER_SIZE];
4904 guint M;
4905 gint captured_len;
4906 gint reported_len;
4907 ieee802154_hints_t *ieee_hints;
4908 gchar *generic_nonce_ptr = NULL;
4909 gchar generic_nonce[13];
4910
4911 ieee_hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ieee802154, 0);
4912
4913 /* Get the captured and on-the-air length of the payload. */
4914 M = IEEE802154_MIC_LENGTH(packet->security_level);
4915 *decrypt_info->rx_mic_length = M;
4916
4917 /* Is the MIC larger than the total amount of data? */
4918 reported_len = tvb_reported_length_remaining(tvb, offset) - M;
4919 if (reported_len < 0) {
4920 /* Yes. Give up. */
4921 *decrypt_info->status = DECRYPT_PACKET_TOO_SMALL;
4922 return NULL;
4923 }
4924 /* Check whether the payload is truncated by a snapshot length. */
4925 if (tvb_bytes_exist(tvb, offset, reported_len)) {
4926 /* It's not, so we have all of the payload. */
4927 captured_len = reported_len;
4928 }
4929 else {
4930 /*
4931 * It is, so we don't have all of the payload - and we don't
4932 * have the MIC, either, as that comes after the payload.
4933 * As the MIC isn't part of the captured data - the captured
4934 * data was cut short before the first byte of the MIC - we
4935 * don't subtract the length of the MIC from the amount of
4936 * captured data.
4937 */
4938 captured_len = tvb_captured_length_remaining(tvb, offset);
4939 }
4940
4941 /* Check if the MIC is present in the captured data. */
4942 have_mic = tvb_bytes_exist(tvb, offset + reported_len, M);
4943 if (have_mic) {
4944 /* It is - save a copy of it. */
4945 tvb_memcpy(tvb, decrypt_info->rx_mic, offset + reported_len, M);
4946 }
4947
4948 /* We need the extended source address. */
4949 if ((packet->key_index == IEEE802154_THR_WELL_KNOWN_KEY_INDEX) &&
4950 (packet->key_source.addr32 == IEEE802154_THR_WELL_KNOWN_KEY_SRC))
4951 {
4952 /* Use the well-known extended address */
4953 srcAddr = IEEE802154_THR_WELL_KNOWN_EXT_ADDR;
4954 } else {
4955 if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
4956 /* The source EUI-64 is included in the headers. */
4957 srcAddr = packet->src64;
4958 }
4959 else if (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT && packet->frame_counter_suppression) {
4960 /* In TSCH mode, the source address is a combination of 802.15 CID, PAN ID and Short Address */
4961 srcAddr = IEEE80215_CID << 40;
4962 srcAddr |= ((guint64)packet->src_pan & 0xffff) << 16;
4963 srcAddr |= packet->src16;
4964 }
4965 else if (ieee_hints && ieee_hints->map_rec && ieee_hints->map_rec->addr64) {
4966 /* Use the hint */
4967 srcAddr = ieee_hints->map_rec->addr64;
4968 }
4969 else {
4970 /* Lookup failed. */
4971 *decrypt_info->status = DECRYPT_PACKET_NO_EXT_SRC_ADDR;
4972 return NULL;
4973 }
4974 }
4975
4976 /*
4977 * CCM* - CTR mode payload encryption
4978 *
4979 */
4980 /* 802.15.4-2015 TSCH mode */
4981 if (packet->frame_counter_suppression) {
4982 tsch_ccm_init_nonce(srcAddr, packet->asn, generic_nonce);
4983 generic_nonce_ptr = generic_nonce;
4984 }
4985
4986 /* Create the CCM* initial block for decryption (Adata=0, M=0, counter=0). */
4987 if (packet->version == IEEE802154_VERSION_2003)
4988 ccm_init_block(tmp, FALSE, 0, srcAddr, packet->frame_counter, packet->key_sequence_counter, 0, NULL);
4989 else
4990 ccm_init_block(tmp, FALSE, 0, srcAddr, packet->frame_counter, packet->security_level, 0, generic_nonce_ptr);
4991
4992 /*
4993 * If the payload is encrypted, so that it's the ciphertext, and we
4994 * have at least one byte of it in the captured data, decrypt the
4995 * ciphertext, and place the plaintext in a new tvb.
4996 */
4997 if (IEEE802154_IS_ENCRYPTED(packet->security_level) && captured_len) {
4998 guint8 *text;
4999 /*
5000 * Make a copy of the ciphertext in heap memory.
5001 *
5002 * We will decrypt the message in-place and then use the buffer as the
5003 * real data for the new tvb.
5004 */
5005 text = (guint8 *)tvb_memdup(pinfo->pool, tvb, offset, captured_len);
5006
5007 /* Perform CTR-mode transformation. */
5008 if (!ccm_ctr_encrypt(decrypt_info->key, tmp, decrypt_info->rx_mic, text, captured_len)) {
5009 wmem_free(pinfo->pool, text);
5010 *decrypt_info->status = DECRYPT_PACKET_DECRYPT_FAILED;
5011 return NULL;
5012 }
5013
5014 /* Create a tvbuff for the plaintext. */
5015 ptext_tvb = tvb_new_child_real_data(tvb, text, captured_len, reported_len);
5016 add_new_data_source(pinfo, ptext_tvb, "Decrypted IEEE 802.15.4 payload");
5017 *decrypt_info->status = DECRYPT_PACKET_SUCCEEDED;
5018 }
5019 else {
5020 /*
5021 * Either the payload isn't encrypted or we don't have any of it
5022 * in the captured data.
5023 */
5024 /* Decrypt the MIC (if present). */
5025 if ((have_mic) && (!ccm_ctr_encrypt(decrypt_info->key, tmp, decrypt_info->rx_mic, NULL, 0))) {
5026 *decrypt_info->status = DECRYPT_PACKET_DECRYPT_FAILED;
5027 return NULL;
5028 }
5029
5030 /* Create a tvbuff for the plaintext. This might result in a zero-length tvbuff. */
5031 ptext_tvb = tvb_new_subset_length_caplen(tvb, offset, captured_len, reported_len);
5032 *decrypt_info->status = DECRYPT_PACKET_SUCCEEDED;
5033 }
5034
5035 /*
5036 * CCM* - CBC-mode message authentication
5037 *
5038 */
5039 /* We can only verify the message if the MIC wasn't truncated. */
5040 if (have_mic) {
5041 unsigned char dec_mic[16];
5042 guint l_m = captured_len;
5043 guint l_a = offset;
5044
5045 /* Adjust the lengths of the plaintext and additional data if unencrypted. */
5046 if (!IEEE802154_IS_ENCRYPTED(packet->security_level)) {
5047 l_a += l_m;
5048 l_m = 0;
5049 }
5050 else if ((packet->version == IEEE802154_VERSION_2003) && !ieee802154_extend_auth)
5051 l_a -= 5; /* Exclude Frame Counter (4 bytes) and Key Sequence Counter (1 byte) from authentication data */
5052
5053
5054 /* Create the CCM* initial block for authentication (Adata!=0, M!=0, counter=l(m)). */
5055 if (packet->version == IEEE802154_VERSION_2003)
5056 ccm_init_block(tmp, TRUE, M, srcAddr, packet->frame_counter, packet->key_sequence_counter, l_m, NULL);
5057 else
5058 ccm_init_block(tmp, TRUE, M, srcAddr, packet->frame_counter, packet->security_level, l_m, generic_nonce_ptr);
5059
5060 /* Compute CBC-MAC authentication tag. */
5061 /*
5062 * And yes, despite the warning in tvbuff.h, I think tvb_get_ptr is the
5063 * right function here since either A) the payload wasn't encrypted, in
5064 * which case l_m is zero, or B) the payload was encrypted, and the tvb
5065 * already points to contiguous memory, since we just allocated it in
5066 * decryption phase.
5067 */
5068 memset(dec_mic, 0, sizeof(dec_mic));
5069 if (!ccm_cbc_mac(decrypt_info->key, tmp, (const gchar *)tvb_memdup(pinfo->pool, tvb, 0, l_a), l_a, tvb_get_ptr(ptext_tvb, 0, l_m), l_m, dec_mic)) {
5070 *decrypt_info->status = DECRYPT_PACKET_MIC_CHECK_FAILED;
5071 }
5072 /* Compare the received MIC with the one we generated. */
5073 else if (memcmp(decrypt_info->rx_mic, dec_mic, M) != 0) {
5074 *decrypt_info->status = DECRYPT_PACKET_MIC_CHECK_FAILED;
5075 }
5076 }
5077
5078 /* Done! */
5079 return ptext_tvb;
5080 } /* dissect_ieee802154_decrypt */
5081
5082 /**
5083 * Creates the CCM* initial block value for IEEE 802.15.4.
5084 *
5085 * @param block Output pointer for the initial block.
5086 * @param adata TRUE if additional auth data is present
5087 * @param M CCM* parameter M.
5088 * @param addr Source extended address.
5089 * @param frame_counter Packet frame counter
5090 * @param level Security level or key_sequence_counter for 802.15.4-2003
5091 * @param ctr_val Value in the last L bytes of the block.
5092 * @param generic_nonce 13-byte nonce to be set by non 802.15.4 calls. If set addr, frame_counter and level are ignored.
5093 */
5094 void
ccm_init_block(gchar * block,gboolean adata,gint M,guint64 addr,guint32 frame_counter,guint8 level,gint ctr_val,const gchar * generic_nonce)5095 ccm_init_block(gchar *block, gboolean adata, gint M, guint64 addr, guint32 frame_counter, guint8 level, gint ctr_val, const gchar *generic_nonce)
5096 {
5097 gint i = 0;
5098
5099 /* Flags: Reserved(0) || Adata || (M-2)/2 || (L-1) */
5100 block[i] = (0x2 - 1); /* (L-1) */
5101 if (M > 0) block[i] |= (((M-2)/2) << 3); /* (M-2)/2 */
5102 if (adata) block[i] |= (1 << 6); /* Adata */
5103 i++;
5104 if (generic_nonce == NULL) {
5105 /* 2003 CCM Nonce: Source Address || Frame Counter || Key Sequence Counter */
5106 /* 2006 CCM* Nonce: Source Address || Frame Counter || Security Level */
5107 block[i++] = (guint8)((addr >> 56) & 0xff);
5108 block[i++] = (guint8)((addr >> 48) & 0xff);
5109 block[i++] = (guint8)((addr >> 40) & 0xff);
5110 block[i++] = (guint8)((addr >> 32) & 0xff);
5111 block[i++] = (guint8)((addr >> 24) & 0xff);
5112 block[i++] = (guint8)((addr >> 16) & 0xff);
5113 block[i++] = (guint8)((addr >> 8) & 0xff);
5114 block[i++] = (guint8)((addr >> 0) & 0xff);
5115 block[i++] = (guint8)((frame_counter >> 24) & 0xff);
5116 block[i++] = (guint8)((frame_counter >> 16) & 0xff);
5117 block[i++] = (guint8)((frame_counter >> 8) & 0xff);
5118 block[i++] = (guint8)((frame_counter >> 0) & 0xff);
5119 block[i++] = level;
5120 } else {
5121 memcpy(&block[i], generic_nonce, 13);
5122 i += 13;
5123 }
5124 /* Plaintext length. */
5125 block[i++] = (guint8)((ctr_val >> 8) & 0xff);
5126 block[i] = (guint8)((ctr_val >> 0) & 0xff);
5127 } /* ccm_init_block */
5128
5129 /**
5130 * Creates the IEEE 802.15.4 TSCH nonce.
5131 *
5132 * @param addr Source extended address.
5133 * @param asn TSCH Absolute Slot Number
5134 * @param generic_nonce 13-byte nonce to returned by this function.
5135 */
5136 static void
tsch_ccm_init_nonce(guint64 addr,guint64 asn,gchar * generic_nonce)5137 tsch_ccm_init_nonce(guint64 addr, guint64 asn, gchar* generic_nonce)
5138 {
5139 gint i = 0;
5140
5141 /* 2015 CCM* Nonce: Source Address || ASN */
5142 generic_nonce[i++] = (guint8)((addr >> 56) & 0xff);
5143 generic_nonce[i++] = (guint8)((addr >> 48) & 0xff);
5144 generic_nonce[i++] = (guint8)((addr >> 40) & 0xff);
5145 generic_nonce[i++] = (guint8)((addr >> 32) & 0xff);
5146 generic_nonce[i++] = (guint8)((addr >> 24) & 0xff);
5147 generic_nonce[i++] = (guint8)((addr >> 16) & 0xff);
5148 generic_nonce[i++] = (guint8)((addr >> 8) & 0xff);
5149 generic_nonce[i++] = (guint8)((addr >> 0) & 0xff);
5150 generic_nonce[i++] = (guint8)((asn >> 32) & 0xff);
5151 generic_nonce[i++] = (guint8)((asn >> 24) & 0xff);
5152 generic_nonce[i++] = (guint8)((asn >> 16) & 0xff);
5153 generic_nonce[i++] = (guint8)((asn >> 8) & 0xff);
5154 generic_nonce[i++] = (guint8)((asn >> 0) & 0xff);
5155 } /* tsch_ccm_init_nonce */
5156
5157 /**
5158 * Perform an in-place CTR-mode encryption/decryption.
5159 *
5160 * @param key Encryption Key.
5161 * @param iv Counter initial value.
5162 * @param mic MIC to encrypt/decrypt.
5163 * @param data Buffer to encrypt/decrypt.
5164 * @param length Length of the buffer.
5165 * @return TRUE on SUCCESS, FALSE on error.
5166 */
5167 gboolean
ccm_ctr_encrypt(const gchar * key,const gchar * iv,gchar * mic,gchar * data,gint length)5168 ccm_ctr_encrypt(const gchar *key, const gchar *iv, gchar *mic, gchar *data, gint length)
5169 {
5170 gcry_cipher_hd_t cipher_hd;
5171
5172 /* Open the cipher. */
5173 if (gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR, 0)) {
5174 return FALSE;
5175 }
5176
5177 /* Set the key and initial value. */
5178 if (gcry_cipher_setkey(cipher_hd, key, 16)) {
5179 gcry_cipher_close(cipher_hd);
5180 return FALSE;
5181 }
5182 if (gcry_cipher_setctr(cipher_hd, iv, 16)) {
5183 gcry_cipher_close(cipher_hd);
5184 return FALSE;
5185 }
5186
5187 /* Decrypt the MIC. */
5188 if (gcry_cipher_encrypt(cipher_hd, mic, 16, NULL, 0)) {
5189 gcry_cipher_close(cipher_hd);
5190 return FALSE;
5191 }
5192 /* Decrypt the payload. */
5193 if (gcry_cipher_encrypt(cipher_hd, data, length, NULL, 0)) {
5194 gcry_cipher_close(cipher_hd);
5195 return FALSE;
5196 }
5197
5198 /* Done with the cipher. */
5199 gcry_cipher_close(cipher_hd);
5200 return TRUE;
5201 } /* ccm_ctr_encrypt */
5202
5203 /**
5204 * Generate a CBC-MAC of the decrypted payload and additional authentication headers.
5205 * @param key Encryption Key.
5206 * @param iv Counter initial value.
5207 * @param a Additional auth headers.
5208 * @param a_len Length of the additional headers.
5209 * @param m Plaintext message.
5210 * @param m_len Length of plaintext message.
5211 * @param mic Output for CBC-MAC.
5212 * @return TRUE on SUCCESS, FALSE on error.
5213 */
5214 gboolean
ccm_cbc_mac(const gchar * key,const gchar * iv,const gchar * a,gint a_len,const gchar * m,gint m_len,gchar * mic)5215 ccm_cbc_mac(const gchar *key, const gchar *iv, const gchar *a, gint a_len, const gchar *m, gint m_len, gchar *mic)
5216 {
5217 gcry_cipher_hd_t cipher_hd;
5218 guint i = 0;
5219 unsigned char block[IEEE802154_CIPHER_SIZE];
5220
5221 /* Open the cipher. */
5222 if (gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC, GCRY_CIPHER_CBC_MAC)) return FALSE;
5223
5224 /* Set the key. */
5225 if (gcry_cipher_setkey(cipher_hd, key, IEEE802154_CIPHER_SIZE)) {
5226 gcry_cipher_close(cipher_hd);
5227 return FALSE;
5228 }
5229
5230 /* Process the initial value. */
5231 if (gcry_cipher_encrypt(cipher_hd, mic, 16, iv, 16)) {
5232 gcry_cipher_close(cipher_hd);
5233 return FALSE;
5234 }
5235
5236 /* Encode L(a) */
5237 i = 0;
5238
5239 /* XXX: GINT_MAX is not defined so #if ... will always be false */
5240 #if (GINT_MAX >= (1LL << 32))
5241 if (a_len >= (1LL << 32)) {
5242 block[i++] = 0xff;
5243 block[i++] = 0xff;
5244 block[i++] = (a_len >> 56) & 0xff;
5245 block[i++] = (a_len >> 48) & 0xff;
5246 block[i++] = (a_len >> 40) & 0xff;
5247 block[i++] = (a_len >> 32) & 0xff;
5248 block[i++] = (a_len >> 24) & 0xff;
5249 block[i++] = (a_len >> 16) & 0xff;
5250 block[i++] = (a_len >> 8) & 0xff;
5251 block[i++] = (a_len >> 0) & 0xff;
5252 }
5253 else
5254 #endif
5255 if (a_len >= ((1 << 16) - (1 << 8))) {
5256 block[i++] = 0xff;
5257 block[i++] = 0xfe;
5258 block[i++] = (a_len >> 24) & 0xff;
5259 block[i++] = (a_len >> 16) & 0xff;
5260 block[i++] = (a_len >> 8) & 0xff;
5261 block[i++] = (a_len >> 0) & 0xff;
5262 }
5263 else {
5264 block[i++] = (a_len >> 8) & 0xff;
5265 block[i++] = (a_len >> 0) & 0xff;
5266 }
5267 /* Append a to get the first block of input (pad if we encounter the end of a). */
5268 while ((i < sizeof(block)) && (a_len > 0)) {
5269 block[i++] = *a++;
5270 a_len--;
5271 }
5272 while (i < sizeof(block)) {
5273 block[i++] = 0;
5274 }
5275
5276 /* Process the first block of AuthData. */
5277 if (gcry_cipher_encrypt(cipher_hd, mic, 16, block, 16)) {
5278 gcry_cipher_close(cipher_hd);
5279 return FALSE;
5280 }
5281
5282 /* Transform and process the remainder of a. */
5283 while (a_len > 0) {
5284 /* Copy and pad. */
5285 if ((guint)a_len >= sizeof(block)) {
5286 memcpy(block, a, sizeof(block));
5287 }
5288 else {
5289 memcpy(block, a, a_len);
5290 memset(block+a_len, 0, sizeof(block)-a_len);
5291 }
5292 /* Adjust pointers. */
5293 a += sizeof(block);
5294 a_len -= (int)sizeof(block);
5295 /* Execute the CBC-MAC algorithm. */
5296 if (gcry_cipher_encrypt(cipher_hd, mic, 16, block, sizeof(block))) {
5297 gcry_cipher_close(cipher_hd);
5298 return FALSE;
5299 }
5300 } /* while */
5301
5302 /* Process the message, m. */
5303 while (m_len > 0) {
5304 /* Copy and pad. */
5305 if ((guint)m_len >= sizeof(block)) {
5306 memcpy(block, m, sizeof(block));
5307 }
5308 else {
5309 memcpy(block, m, m_len);
5310 memset(block+m_len, 0, sizeof(block)-m_len);
5311 }
5312 /* Adjust pointers. */
5313 m += sizeof(block);
5314 m_len -= (int)sizeof(block);
5315 /* Execute the CBC-MAC algorithm. */
5316 if (gcry_cipher_encrypt(cipher_hd, mic, 16, block, sizeof(block))) {
5317 gcry_cipher_close(cipher_hd);
5318 return FALSE;
5319 }
5320 }
5321
5322 /* Done with the cipher. */
5323 gcry_cipher_close(cipher_hd);
5324 return TRUE;
5325 } /* ccm_cbc_mac */
5326
5327 /* Key hash function. */
ieee802154_short_addr_hash(gconstpointer key)5328 guint ieee802154_short_addr_hash(gconstpointer key)
5329 {
5330 return (((const ieee802154_short_addr *)key)->addr) | (((const ieee802154_short_addr *)key)->pan << 16);
5331 }
5332
5333 /* Key equal function. */
ieee802154_short_addr_equal(gconstpointer a,gconstpointer b)5334 gboolean ieee802154_short_addr_equal(gconstpointer a, gconstpointer b)
5335 {
5336 return (((const ieee802154_short_addr *)a)->pan == ((const ieee802154_short_addr *)b)->pan) &&
5337 (((const ieee802154_short_addr *)a)->addr == ((const ieee802154_short_addr *)b)->addr);
5338 }
5339
5340 /* Key hash function. */
ieee802154_long_addr_hash(gconstpointer key)5341 guint ieee802154_long_addr_hash(gconstpointer key)
5342 {
5343 return (guint)(((const ieee802154_long_addr *)key)->addr) & 0xFFFFFFFF;
5344 }
5345
5346 /* Key equal function. */
ieee802154_long_addr_equal(gconstpointer a,gconstpointer b)5347 gboolean ieee802154_long_addr_equal(gconstpointer a, gconstpointer b)
5348 {
5349 return (((const ieee802154_long_addr *)a)->addr == ((const ieee802154_long_addr *)b)->addr);
5350 }
5351
5352 /* Set MAC key function. */
ieee802154_set_mac_key(ieee802154_packet * packet,unsigned char * key,unsigned char * alt_key,ieee802154_key_t * uat_key)5353 static guint ieee802154_set_mac_key(ieee802154_packet *packet, unsigned char *key, unsigned char *alt_key, ieee802154_key_t *uat_key)
5354 {
5355 ieee802154_set_key_func func = (ieee802154_set_key_func)wmem_tree_lookup32(mac_key_hash_handlers, uat_key->hash_type);
5356
5357 if (func != NULL)
5358 return func(packet, key, alt_key, uat_key);
5359
5360 /* Right now, KEY_HASH_NONE and KEY_HASH_ZIP are not registered because they
5361 work with this "default" behavior */
5362 if (packet->key_index == uat_key->key_index)
5363 {
5364 memcpy(key, uat_key->key, IEEE802154_CIPHER_SIZE);
5365 return 1;
5366 }
5367
5368 return 0;
5369 }
5370
5371 /**
5372 * Creates a record that maps the given short address and pan to a long (extended) address.
5373 * @param short_addr 16-bit short address
5374 * @param pan 16-bit PAN id
5375 * @param long_addr 64-bit long (extended) address
5376 * @param proto pointer to name of current protocol
5377 * @param fnum Frame number this mapping became valid
5378 * @return TRUE Record was updated, FALSE Couldn't find it
5379 */
ieee802154_addr_update(ieee802154_map_tab_t * au_ieee802154_map,guint16 short_addr,guint16 pan,guint64 long_addr,const char * proto,guint fnum)5380 ieee802154_map_rec *ieee802154_addr_update(ieee802154_map_tab_t *au_ieee802154_map,
5381 guint16 short_addr, guint16 pan, guint64 long_addr, const char *proto, guint fnum)
5382 {
5383 ieee802154_short_addr addr16;
5384 ieee802154_map_rec *p_map_rec;
5385 gpointer old_key;
5386
5387 /* Look up short address hash */
5388 addr16.pan = pan;
5389 addr16.addr = short_addr;
5390 p_map_rec = (ieee802154_map_rec *)g_hash_table_lookup(au_ieee802154_map->short_table, &addr16);
5391
5392 /* Update mapping record */
5393 if (p_map_rec) {
5394 /* record already exists */
5395 if ( p_map_rec->addr64 == long_addr ) {
5396 /* no change */
5397 return p_map_rec;
5398 }
5399 else {
5400 /* mark current mapping record invalid */
5401 p_map_rec->end_fnum = fnum;
5402 }
5403 }
5404
5405 /* create a new mapping record */
5406 p_map_rec = wmem_new(wmem_file_scope(), ieee802154_map_rec);
5407 p_map_rec->proto = proto;
5408 p_map_rec->start_fnum = fnum;
5409 p_map_rec->end_fnum = 0;
5410 p_map_rec->addr64 = long_addr;
5411
5412 /* link new mapping record to addr hash tables */
5413 if ( g_hash_table_lookup_extended(au_ieee802154_map->short_table, &addr16, &old_key, NULL) ) {
5414 /* update short addr hash table, reusing pointer to old key */
5415 g_hash_table_insert(au_ieee802154_map->short_table, old_key, p_map_rec);
5416 } else {
5417 /* create new hash entry */
5418 g_hash_table_insert(au_ieee802154_map->short_table, wmem_memdup(wmem_file_scope(), &addr16, sizeof(addr16)), p_map_rec);
5419 }
5420
5421 if ( g_hash_table_lookup_extended(au_ieee802154_map->long_table, &long_addr, &old_key, NULL) ) {
5422 /* update long addr hash table, reusing pointer to old key */
5423 g_hash_table_insert(au_ieee802154_map->long_table, old_key, p_map_rec);
5424 } else {
5425 /* create new hash entry */
5426 g_hash_table_insert(au_ieee802154_map->long_table, wmem_memdup(wmem_file_scope(), &long_addr, sizeof(long_addr)), p_map_rec);
5427 }
5428
5429 return p_map_rec;
5430 } /* ieee802154_addr_update */
5431
5432 /**
5433 * Marks a mapping record associated with device with short_addr
5434 * as invalid at a certain frame number, typically when a
5435 * disassociation occurs.
5436 *
5437 * @param short_addr 16-bit short address
5438 * @param pan 16-bit PAN id
5439 * @param fnum Frame number when mapping became invalid
5440 * @return TRUE Record was updated, FALSE Couldn't find it
5441 */
ieee802154_short_addr_invalidate(guint16 short_addr,guint16 pan,guint fnum)5442 gboolean ieee802154_short_addr_invalidate(guint16 short_addr, guint16 pan, guint fnum)
5443 {
5444 ieee802154_short_addr addr16;
5445 ieee802154_map_rec *map_rec;
5446
5447 addr16.pan = pan;
5448 addr16.addr = short_addr;
5449
5450 map_rec = (ieee802154_map_rec *)g_hash_table_lookup(ieee802154_map.short_table, &addr16);
5451 if ( map_rec ) {
5452 /* indicates this mapping is invalid at frame fnum */
5453 map_rec->end_fnum = fnum;
5454 return TRUE;
5455 }
5456
5457 return FALSE;
5458 } /* ieee802154_short_addr_invalidate */
5459
5460 /**
5461 * Mark a mapping record associated with device with long_addr
5462 * as invalid at a certain frame number, typically when a
5463 * disassociation occurs.
5464 *
5465 * @param long_addr 16-bit short address
5466 * @param fnum Frame number when mapping became invalid
5467 * @return TRUE If record was updated, FALSE otherwise
5468 */
ieee802154_long_addr_invalidate(guint64 long_addr,guint fnum)5469 gboolean ieee802154_long_addr_invalidate(guint64 long_addr, guint fnum)
5470 {
5471 ieee802154_map_rec *map_rec;
5472
5473 map_rec = (ieee802154_map_rec *)g_hash_table_lookup(ieee802154_map.long_table, &long_addr);
5474 if ( map_rec ) {
5475 /* indicates this mapping is invalid at frame fnum */
5476 map_rec->end_fnum = fnum;
5477 return TRUE;
5478 }
5479
5480 return FALSE;
5481 } /* ieee802154_long_addr_invalidate */
5482
5483 /**
5484 * Init routine for the IEEE 802.15.4 dissector. Creates hash
5485 * tables for mapping between 16-bit to 64-bit addresses and
5486 * populates them with static address pairs from a UAT
5487 * preference table.
5488 */
5489 static void
proto_init_ieee802154(void)5490 proto_init_ieee802154(void)
5491 {
5492 guint i;
5493
5494 ieee802154_map.short_table = g_hash_table_new(ieee802154_short_addr_hash, ieee802154_short_addr_equal);
5495 ieee802154_map.long_table = g_hash_table_new(ieee802154_long_addr_hash, ieee802154_long_addr_equal);
5496 /* Reload the hash table from the static address UAT. */
5497 for (i=0; (i<num_static_addrs) && (static_addrs); i++) {
5498 ieee802154_addr_update(&ieee802154_map,(guint16)static_addrs[i].addr16, (guint16)static_addrs[i].pan,
5499 pntoh64(static_addrs[i].eui64), ieee802154_user, IEEE802154_USER_MAPPING);
5500 } /* for */
5501 } /* proto_init_ieee802154 */
5502
5503 /**
5504 * Cleanup for the IEEE 802.15.4 dissector.
5505 */
5506 static void
proto_cleanup_ieee802154(void)5507 proto_cleanup_ieee802154(void)
5508 {
5509 g_hash_table_destroy(ieee802154_map.short_table);
5510 g_hash_table_destroy(ieee802154_map.long_table);
5511 }
5512
5513 /* Returns the prompt string for the Decode-As dialog. */
ieee802154_da_prompt(packet_info * pinfo _U_,gchar * result)5514 static void ieee802154_da_prompt(packet_info *pinfo _U_, gchar* result)
5515 {
5516 ieee802154_hints_t *hints;
5517 hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ieee802154, 0);
5518 if (hints)
5519 g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "IEEE 802.15.4 PAN 0x%04x as", hints->src_pan);
5520 else
5521 g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "IEEE 802.15.4 PAN Unknown");
5522 } /* iee802154_da_prompt */
5523
5524 /* Returns the value to index the panid decode table with (source PAN)*/
ieee802154_da_value(packet_info * pinfo _U_)5525 static gpointer ieee802154_da_value(packet_info *pinfo _U_)
5526 {
5527 ieee802154_hints_t *hints;
5528 hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ieee802154, 0);
5529 if (hints)
5530 return GUINT_TO_POINTER((guint)(hints->src_pan));
5531 else
5532 return NULL;
5533 } /* iee802154_da_value */
5534
ieee802154_conv_get_filter_type(conv_item_t * conv,conv_filter_type_e filter)5535 static const char* ieee802154_conv_get_filter_type(conv_item_t* conv, conv_filter_type_e filter)
5536 {
5537 if (filter == CONV_FT_SRC_ADDRESS) {
5538 if (conv->src_address.type == ieee802_15_4_short_address_type)
5539 return "wpan.src16";
5540 else if (conv->src_address.type == AT_EUI64)
5541 return "wpan.src64";
5542 }
5543
5544 if (filter == CONV_FT_DST_ADDRESS) {
5545 if (conv->dst_address.type == ieee802_15_4_short_address_type)
5546 return "wpan.dst16";
5547 else if (conv->dst_address.type == AT_EUI64)
5548 return "wpan.dst64";
5549 }
5550
5551 if (filter == CONV_FT_ANY_ADDRESS) {
5552 if (conv->src_address.type == ieee802_15_4_short_address_type)
5553 return "wpan.addr16";
5554 else if (conv->src_address.type == AT_EUI64)
5555 return "wpan.addr64";
5556 }
5557
5558 return CONV_FILTER_INVALID;
5559 }
5560
5561 static ct_dissector_info_t ieee802154_ct_dissector_info = {&ieee802154_conv_get_filter_type };
5562
ieee802154_conversation_packet(void * pct,packet_info * pinfo,epan_dissect_t * edt _U_,const void * vip _U_)5563 static tap_packet_status ieee802154_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip _U_)
5564 {
5565 conv_hash_t *hash = (conv_hash_t*)pct;
5566
5567 add_conversation_table_data(hash, &pinfo->dl_src, &pinfo->dl_dst, 0, 0, 1,
5568 pinfo->fd->pkt_len, &pinfo->rel_ts, &pinfo->abs_ts,
5569 &ieee802154_ct_dissector_info, ENDPOINT_NONE);
5570
5571 return TAP_PACKET_REDRAW;
5572 }
5573
ieee802154_host_get_filter_type(hostlist_talker_t * host,conv_filter_type_e filter)5574 static const char* ieee802154_host_get_filter_type(hostlist_talker_t* host, conv_filter_type_e filter)
5575 {
5576 if (filter == CONV_FT_ANY_ADDRESS) {
5577 if (host->myaddress.type == ieee802_15_4_short_address_type)
5578 return "wpan.addr16";
5579 else if (host->myaddress.type == AT_EUI64)
5580 return "wpan.addr64";
5581 }
5582
5583 return CONV_FILTER_INVALID;
5584 }
5585
5586 static hostlist_dissector_info_t ieee802154_host_dissector_info = {&ieee802154_host_get_filter_type };
5587
ieee802154_hostlist_packet(void * pit,packet_info * pinfo,epan_dissect_t * edt _U_,const void * vip _U_)5588 static tap_packet_status ieee802154_hostlist_packet(void *pit, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip _U_)
5589 {
5590 conv_hash_t *hash = (conv_hash_t*)pit;
5591
5592 /* Take two "add" passes per packet, adding for each direction, ensures that all
5593 packets are counted properly (even if address is sending to itself)
5594 XXX - this could probably be done more efficiently inside hostlist_table */
5595 add_hostlist_table_data(hash, &pinfo->dl_src, 0, TRUE, 1,
5596 pinfo->fd->pkt_len, &ieee802154_host_dissector_info, ENDPOINT_NONE);
5597 add_hostlist_table_data(hash, &pinfo->dl_dst, 0, FALSE, 1,
5598 pinfo->fd->pkt_len, &ieee802154_host_dissector_info, ENDPOINT_NONE);
5599
5600 return TAP_PACKET_REDRAW;
5601 }
5602
ieee802154_filter_valid(packet_info * pinfo)5603 static gboolean ieee802154_filter_valid(packet_info *pinfo)
5604 {
5605 return proto_is_frame_protocol(pinfo->layers, "wpan")
5606 && ((pinfo->dl_src.type == ieee802_15_4_short_address_type) || (pinfo->dl_src.type == AT_EUI64))
5607 && ((pinfo->dl_dst.type == ieee802_15_4_short_address_type) || (pinfo->dl_dst.type == AT_EUI64));
5608 }
5609
ieee802154_build_filter(packet_info * pinfo)5610 static gchar* ieee802154_build_filter(packet_info *pinfo)
5611 {
5612 return g_strdup_printf("wpan.%s eq %s and wpan.%s eq %s",
5613 (pinfo->dl_src.type == ieee802_15_4_short_address_type) ? "addr16" : "addr64",
5614 address_to_str(pinfo->pool, &pinfo->dl_src),
5615 (pinfo->dl_dst.type == ieee802_15_4_short_address_type) ? "addr16" : "addr64",
5616 address_to_str(pinfo->pool, &pinfo->dl_dst));
5617 }
5618
5619 /**
5620 * IEEE 802.15.4 protocol registration routine.
5621 */
proto_register_ieee802154(void)5622 void proto_register_ieee802154(void)
5623 {
5624 /* Protocol fields */
5625 static hf_register_info hf_phy[] = {
5626 /* PHY level */
5627
5628 { &hf_ieee802154_nonask_phy_preamble,
5629 { "Preamble", "wpan-nonask-phy.preamble", FT_UINT32, BASE_HEX, NULL, 0x0,
5630 NULL, HFILL }},
5631
5632 { &hf_ieee802154_nonask_phy_sfd,
5633 { "Start of Frame Delimiter", "wpan-nonask-phy.sfd", FT_UINT8, BASE_HEX, NULL, 0x0,
5634 NULL, HFILL }},
5635
5636 { &hf_ieee802154_nonask_phy_length,
5637 { "Frame Length", "wpan-nonask-phy.frame_length", FT_UINT8, BASE_HEX, NULL,
5638 IEEE802154_PHY_LENGTH_MASK, NULL, HFILL }},
5639
5640 { &hf_ieee802154_nonask_phr,
5641 { "PHR", "wpan-nonask-phy.phr", FT_UINT8, BASE_HEX, NULL,
5642 0x0, NULL, HFILL }},
5643 };
5644
5645 static hf_register_info hf[] = {
5646
5647 { &hf_ieee802154_frame_length,
5648 { "Frame Length", "wpan.frame_length", FT_UINT8, BASE_DEC, NULL, 0x0,
5649 "Frame Length as reported from lower layer", HFILL }},
5650
5651 { &hf_ieee802154_fcf,
5652 { "Frame Control Field", "wpan.fcf", FT_UINT16, BASE_HEX, NULL,
5653 0x0, NULL, HFILL }},
5654
5655 { &hf_ieee802154_frame_type,
5656 { "Frame Type", "wpan.frame_type", FT_UINT16, BASE_HEX, VALS(ieee802154_frame_types),
5657 IEEE802154_FCF_TYPE_MASK, NULL, HFILL }},
5658
5659 { &hf_ieee802154_security,
5660 { "Security Enabled", "wpan.security", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_SEC_EN,
5661 "Whether security operations are performed at the MAC layer or not.", HFILL }},
5662
5663 { &hf_ieee802154_pending,
5664 { "Frame Pending", "wpan.pending", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_FRAME_PND,
5665 "Indication of additional packets waiting to be transferred from the source device.", HFILL }},
5666
5667 { &hf_ieee802154_ack_request,
5668 { "Acknowledge Request", "wpan.ack_request", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_ACK_REQ,
5669 "Whether the sender of this packet requests acknowledgment or not.", HFILL }},
5670
5671 { &hf_ieee802154_pan_id_compression,
5672 { "PAN ID Compression", "wpan.pan_id_compression", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_PAN_ID_COMPRESSION,
5673 "Whether this packet contains the PAN ID or not.", HFILL }},
5674
5675 { &hf_ieee802154_fcf_reserved,
5676 { "Reserved", "wpan.fcf.reserved", FT_BOOLEAN, 16, NULL, 0x0080,
5677 NULL, HFILL }},
5678
5679 { &hf_ieee802154_seqno_suppression,
5680 { "Sequence Number Suppression", "wpan.seqno_suppression", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_SEQNO_SUPPRESSION,
5681 "Whether this packet contains the Sequence Number or not.", HFILL }},
5682
5683 { &hf_ieee802154_ie_present,
5684 { "Information Elements Present", "wpan.ie_present", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_IE_PRESENT,
5685 "Whether this packet contains the Information Elements or not.", HFILL }},
5686
5687 { &hf_ieee802154_dst_addr_mode,
5688 { "Destination Addressing Mode", "wpan.dst_addr_mode", FT_UINT16, BASE_HEX, VALS(ieee802154_addr_modes),
5689 IEEE802154_FCF_DADDR_MASK, NULL, HFILL }},
5690
5691 { &hf_ieee802154_version,
5692 { "Frame Version", "wpan.version", FT_UINT16, BASE_DEC, VALS(ieee802154_frame_versions),
5693 IEEE802154_FCF_VERSION, NULL, HFILL }},
5694
5695 { &hf_ieee802154_src_addr_mode,
5696 { "Source Addressing Mode", "wpan.src_addr_mode", FT_UINT16, BASE_HEX, VALS(ieee802154_addr_modes),
5697 IEEE802154_FCF_SADDR_MASK, NULL, HFILL }},
5698
5699 /* 802.15.4-2015 Multipurpose frame control fields */
5700 { &hf_ieee802154_mpf_long_frame_control,
5701 { "Long Frame Control", "wpan.long_frame_control", FT_BOOLEAN, 16, NULL, IEEE802154_MPF_FCF_LONG_FC,
5702 "Whether this frame control field uses one or two octets.", HFILL }},
5703
5704 { &hf_ieee802154_mpf_dst_addr_mode,
5705 { "Destination Addressing Mode", "wpan.dst_addr_mode", FT_UINT16, BASE_HEX, VALS(ieee802154_addr_modes),
5706 IEEE802154_MPF_FCF_DADDR_MASK, NULL, HFILL }},
5707
5708 { &hf_ieee802154_mpf_src_addr_mode,
5709 { "Source Addressing Mode", "wpan.src_addr_mode", FT_UINT16, BASE_HEX, VALS(ieee802154_addr_modes),
5710 IEEE802154_MPF_FCF_SADDR_MASK, NULL, HFILL }},
5711
5712 { &hf_ieee802154_mpf_pan_id_present,
5713 { "PAN ID Present", "wpan.pan_id_present", FT_BOOLEAN, 16, NULL, IEEE802154_MPF_FCF_PAN_ID_PRESENT,
5714 "Whether this packet contains the destination PAN ID or not", HFILL }},
5715
5716 { &hf_ieee802154_mpf_security,
5717 { "Security Enabled", "wpan.security", FT_BOOLEAN, 16, NULL, IEEE802154_MPF_FCF_SEC_EN,
5718 "Whether security operations are performed at the MAC layer or not.", HFILL }},
5719
5720 { &hf_ieee802154_mpf_seqno_suppression,
5721 { "Sequence Number Suppression", "wpan.seqno_suppression", FT_BOOLEAN, 16, NULL, IEEE802154_MPF_FCF_SEQNO_SUPPRESSION,
5722 "Whether this packet contains the Sequence Number or not.", HFILL }},
5723
5724 { &hf_ieee802154_mpf_pending,
5725 { "Frame Pending", "wpan.pending", FT_BOOLEAN, 16, NULL, IEEE802154_MPF_FCF_FRAME_PND,
5726 "Indication of additional packets waiting to be transferred from the source device.", HFILL }},
5727
5728 { &hf_ieee802154_mpf_version,
5729 { "Multipurpose Frame Version", "wpan.mpf_version", FT_UINT16, BASE_DEC, NULL,
5730 IEEE802154_MPF_FCF_VERSION, NULL, HFILL }},
5731
5732 { &hf_ieee802154_mpf_ack_request,
5733 { "Acknowledge Request", "wpan.ack_request", FT_BOOLEAN, 16, NULL, IEEE802154_MPF_FCF_ACK_REQ,
5734 "Whether the sender of this packet requests acknowledgment or not.", HFILL }},
5735
5736 { &hf_ieee802154_mpf_ie_present,
5737 { "Information Elements Present", "wpan.ie_present", FT_BOOLEAN, 16, NULL, IEEE802154_MPF_FCF_IE_PRESENT,
5738 "Whether this packet contains the Information Elements or not.", HFILL }},
5739
5740 { &hf_ieee802154_seqno,
5741 { "Sequence Number", "wpan.seq_no", FT_UINT8, BASE_DEC, NULL, 0x0,
5742 NULL, HFILL }},
5743
5744 { &hf_ieee802154_dst_panID,
5745 { "Destination PAN", "wpan.dst_pan", FT_UINT16, BASE_HEX, NULL, 0x0,
5746 NULL, HFILL }},
5747
5748 { &hf_ieee802154_dst16,
5749 { "Destination", "wpan.dst16", FT_UINT16, BASE_HEX, NULL, 0x0,
5750 NULL, HFILL }},
5751
5752 { &hf_ieee802154_dst64,
5753 { "Destination", "wpan.dst64", FT_EUI64, BASE_NONE, NULL, 0x0,
5754 NULL, HFILL }},
5755
5756 { &hf_ieee802154_src_panID,
5757 { "Source PAN", "wpan.src_pan", FT_UINT16, BASE_HEX, NULL, 0x0,
5758 NULL, HFILL }},
5759
5760 { &hf_ieee802154_src16,
5761 { "Source", "wpan.src16", FT_UINT16, BASE_HEX, NULL, 0x0,
5762 NULL, HFILL }},
5763
5764 { &hf_ieee802154_src64,
5765 { "Extended Source", "wpan.src64", FT_EUI64, BASE_NONE, NULL, 0x0,
5766 NULL, HFILL }},
5767
5768 { &hf_ieee802154_addr16,
5769 { "Address", "wpan.addr16", FT_UINT16, BASE_HEX, NULL, 0x0,
5770 NULL, HFILL }},
5771
5772 { &hf_ieee802154_addr64,
5773 { "Extended Address", "wpan.addr64", FT_EUI64, BASE_NONE, NULL, 0x0,
5774 NULL, HFILL }},
5775
5776 { &hf_ieee802154_src64_origin,
5777 { "Origin", "wpan.src64.origin", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
5778 NULL, HFILL }},
5779
5780 { &hf_ieee802154_fcs,
5781 { "FCS", "wpan.fcs", FT_UINT16, BASE_HEX, NULL, 0x0,
5782 NULL, HFILL }},
5783
5784 { &hf_ieee802154_fcs32,
5785 { "FCS", "wpan.fcs32", FT_UINT32, BASE_HEX, NULL, 0x0,
5786 NULL, HFILL }},
5787
5788 { &hf_ieee802154_rssi,
5789 { "RSSI", "wpan.rssi", FT_INT8, BASE_DEC|BASE_UNIT_STRING, &units_decibels, 0x0,
5790 "Received Signal Strength", HFILL }},
5791
5792 { &hf_ieee802154_fcs_ok,
5793 { "FCS Valid", "wpan.fcs_ok", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
5794 NULL, HFILL }},
5795
5796 { &hf_ieee802154_correlation,
5797 { "LQI Correlation Value", "wpan.correlation", FT_UINT8, BASE_DEC, NULL, 0x0,
5798 NULL, HFILL }},
5799
5800 /* Information Elements */
5801
5802 { &hf_ieee802154_ie_unknown_content,
5803 { "Unknown Content", "wpan.ie.unknown_content", FT_BYTES, SEP_SPACE, NULL, 0x0,
5804 NULL, HFILL }},
5805
5806 /* Header IE */
5807
5808 { &hf_ieee802154_header_ies,
5809 { "Header IEs", "wpan.header_ie", FT_NONE, BASE_NONE, NULL,
5810 0x0, NULL, HFILL }},
5811
5812 { &hf_ieee802154_header_ie_tlv,
5813 { "IE Header", "wpan.header_ie_tlv", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL}},
5814
5815 { &hf_ieee802154_header_ie_type,
5816 { "Type", "wpan.header_ie.type", FT_UINT16, BASE_DEC, VALS(ieee802154_ie_types),
5817 IEEE802154_HEADER_IE_TYPE_MASK, NULL, HFILL }},
5818
5819 { &hf_ieee802154_header_ie_id,
5820 { "Id", "wpan.header_ie.id", FT_UINT16, BASE_HEX, VALS(ieee802154_header_ie_names),
5821 IEEE802154_HEADER_IE_ID_MASK, NULL, HFILL }},
5822
5823 { &hf_ieee802154_header_ie_length,
5824 { "Length", "wpan.header_ie.length", FT_UINT16, BASE_DEC, NULL,
5825 IEEE802154_HEADER_IE_LENGTH_MASK, NULL, HFILL }},
5826
5827
5828 /* Individual Header IEs */
5829
5830 { &hf_ieee802154_hie_unsupported,
5831 { "Unsupported Header IE", "wpan.header_ie.unsupported", FT_NONE, BASE_NONE, NULL, 0x0,
5832 NULL, HFILL }},
5833
5834 { &hf_ieee802154_hie_ht1,
5835 { "Header Termination 1 IE (Payload IEs follow)", "wpan.header_ie.ht1", FT_NONE, BASE_NONE, NULL, 0x0,
5836 NULL, HFILL }},
5837
5838 { &hf_ieee802154_hie_ht2,
5839 { "Header Termination 2 IE (Payload follows)", "wpan.header_ie.ht2", FT_NONE, BASE_NONE, NULL, 0x0,
5840 NULL, HFILL }},
5841
5842
5843 /* Time correction IE */
5844 { &hf_ieee802154_hie_time_correction,
5845 { "Time Correction IE", "wpan.header_ie.time_correction", FT_NONE, BASE_NONE, NULL, 0x0,
5846 NULL, HFILL }},
5847
5848 { &hf_ieee802154_hie_time_correction_time_sync_info,
5849 { "Time Sync Info", "wpan.header_ie.time_correction.time_sync_info", FT_UINT16, BASE_HEX, NULL, 0x0,
5850 NULL, HFILL }},
5851
5852 { &hf_ieee802154_nack,
5853 { "Nack", "wpan.nack", FT_BOOLEAN, 16, TFS(&hf_ieee802154_nack_tfs), 0x8000,
5854 NULL, HFILL }},
5855
5856 { &hf_ieee802154_hie_time_correction_value,
5857 { "Time Correction", "wpan.header_ie.time_correction.value", FT_INT16, BASE_DEC|BASE_UNIT_STRING, &units_microseconds, 0x0FFF,
5858 "Time correction in microseconds", HFILL }},
5859
5860 /* CSL IE */
5861 { &hf_ieee802154_hie_csl,
5862 { "CSL IE", "wpan.header_ie.csl", FT_NONE, BASE_NONE, NULL, 0x0,
5863 NULL, HFILL }},
5864
5865 { &hf_ieee802154_hie_csl_phase,
5866 { "Phase", "wpan.header_ie.csl.phase", FT_INT16, BASE_DEC, NULL, 0x0,
5867 "CSL Phase in units of 10 symbols", HFILL }},
5868
5869 { &hf_ieee802154_hie_csl_period,
5870 { "Period", "wpan.header_ie.csl.period", FT_INT16, BASE_DEC, NULL, 0x0,
5871 "CSL Period in units of 10 symbols", HFILL }},
5872
5873 { &hf_ieee802154_hie_csl_rendezvous_time,
5874 { "Rendezvous Time", "wpan.header_ie.csl.rendezvous_time", FT_INT16, BASE_DEC, NULL, 0x0,
5875 "CSL Rendezvous Time in units of 10 symbols", HFILL }},
5876
5877 /* Global Time IE */
5878 { &hf_ieee802154_hie_global_time,
5879 { "Global Time IE", "wpan.header_ie.global_time", FT_NONE, BASE_NONE, NULL, 0x0,
5880 NULL, HFILL }},
5881
5882 { &hf_ieee802154_hie_global_time_value,
5883 { "Global Time", "wpan.header_ie.global_time.value", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0x0,
5884 NULL, HFILL }},
5885
5886 /* Vendor Specific IE */
5887 { &hf_ieee802154_hie_vendor_specific,
5888 { "Vendor Specific IE", "wpan.header_ie.vendor_specific", FT_NONE, BASE_NONE, NULL, 0x0,
5889 NULL, HFILL }},
5890
5891 { &hf_ieee802154_hie_vendor_specific_vendor_oui,
5892 { "Vendor OUI", "wpan.header_ie.vendor_specific.vendor_oui", FT_UINT24, BASE_OUI, NULL, 0x0,
5893 NULL, HFILL }},
5894
5895 { &hf_ieee802154_hie_vendor_specific_content,
5896 { "Vendor Content", "wpan.header_ie.vendor_specific.content", FT_BYTES, SEP_SPACE, NULL, 0x0,
5897 NULL, HFILL }},
5898
5899 /* Payload IEs */
5900
5901 { &hf_ieee802154_payload_ies,
5902 { "Payload IEs", "wpan.payload_ie", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5903
5904 { &hf_ieee802154_payload_ie_tlv,
5905 { "IE Header", "wpan.payload_ie_tlv", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
5906
5907 { &hf_ieee802154_payload_ie_type,
5908 { "Type", "wpan.payload_ie.type", FT_UINT16, BASE_DEC, VALS(ieee802154_ie_types),
5909 IEEE802154_PAYLOAD_IE_TYPE_MASK, NULL, HFILL }},
5910
5911 { &hf_ieee802154_payload_ie_id,
5912 { "Id", "wpan.payload_ie.id", FT_UINT16, BASE_HEX, VALS(ieee802154_payload_ie_names),
5913 IEEE802154_PAYLOAD_IE_ID_MASK, NULL, HFILL }},
5914
5915 { &hf_ieee802154_payload_ie_length,
5916 { "Length", "wpan.payload_ie.length", FT_UINT16, BASE_DEC, NULL,
5917 IEEE802154_PAYLOAD_IE_LENGTH_MASK, NULL, HFILL }},
5918
5919
5920 /* Individual Payload IEs */
5921
5922 { &hf_ieee802154_pie_unsupported,
5923 { "Unknown Payload IE", "wpan.payload_ie.unknown", FT_NONE, BASE_NONE, NULL, 0x0,
5924 NULL, HFILL }},
5925
5926 { &hf_ieee802154_pie_termination,
5927 { "Payload Termination IE", "wpan.payload_ie.termination", FT_NONE, BASE_NONE, NULL, 0x0,
5928 NULL, HFILL }},
5929
5930 { &hf_ieee802154_pie_vendor,
5931 { "Vendor Specific IE", "wpan.payload_ie.vendor", FT_NONE, BASE_NONE, NULL, 0x0,
5932 NULL, HFILL }},
5933
5934 { &hf_ieee802154_pie_vendor_oui,
5935 { "Vendor OUI", "wpan.payload_ie.vendor.oui", FT_UINT24, BASE_OUI, NULL, 0x0,
5936 NULL, HFILL }},
5937
5938 { &hf_ieee802154_mlme,
5939 { "MLME IE", "wpan.mlme", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5940
5941 { &hf_ieee802154_psie_type,
5942 { "Type", "wpan.mlme.ie.type", FT_UINT16, BASE_DEC, VALS(ieee802154_psie_types),
5943 IEEE802154_PSIE_TYPE_MASK, NULL, HFILL }},
5944
5945 { &hf_ieee802154_psie,
5946 { "MLME Sub IE", "wpan.mlme.ie", FT_UINT16, BASE_HEX, NULL,
5947 0x0, NULL, HFILL }},
5948
5949 { &hf_ieee802154_psie_id_short,
5950 { "Sub ID", "wpan.mlme.ie.id", FT_UINT16, BASE_HEX, VALS(ieee802154_psie_names),
5951 IEEE802154_PSIE_ID_MASK_SHORT, NULL, HFILL }},
5952
5953 { &hf_ieee802154_psie_length_short,
5954 { "Length", "wpan.mlme.ie.length", FT_UINT16, BASE_DEC, NULL,
5955 IEEE802154_PSIE_LENGTH_MASK_SHORT, NULL, HFILL }},
5956
5957 { &hf_ieee802154_psie_id_long,
5958 { "Sub ID", "wpan.mlme.ie.id", FT_UINT16, BASE_HEX, VALS(ieee802154_psie_names),
5959 IEEE802154_PSIE_ID_MASK_LONG, NULL, HFILL }},
5960
5961 { &hf_ieee802154_psie_length_long,
5962 { "Length", "wpan.mlme.ie.length", FT_UINT16, BASE_DEC, NULL,
5963 IEEE802154_PSIE_LENGTH_MASK_LONG, NULL, HFILL }},
5964
5965 { &hf_ieee802154_mlme_ie_unsupported,
5966 { "Unsupported Sub IE", "wpan.mlme.unsupported", FT_NONE, BASE_NONE, NULL,
5967 0, NULL, HFILL }},
5968
5969 { &hf_ieee802154_mlme_ie_data,
5970 { "Data", "wpan.mlme.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5971
5972 { &hf_ieee802154_psie_eb_filter,
5973 { "Enhanced Beacon Filter", "wpan.eb_filter", FT_UINT8, BASE_HEX, NULL,
5974 0, NULL, HFILL }},
5975
5976 { &hf_ieee802154_psie_eb_filter_pjoin,
5977 { "Permit Join Filter", "wpan.eb_filter.pjoin", FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled),
5978 IEEE802154_MLME_PSIE_EB_FLT_PJOIN, NULL, HFILL }},
5979
5980 { &hf_ieee802154_psie_eb_filter_lqi,
5981 { "LQI Filter", "wpan.eb_filter.lqi", FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled),
5982 IEEE802154_MLME_PSIE_EB_FLT_LQI, NULL, HFILL }},
5983
5984 { &hf_ieee802154_psie_eb_filter_lqi_min,
5985 { "Minimum LQI", "wpan.eb_filter.lqi_minimum", FT_UINT8, BASE_DEC, NULL,
5986 0x0, NULL, HFILL }},
5987
5988 { &hf_ieee802154_psie_eb_filter_percent,
5989 { "Probability to Respond", "wpan.eb_filter.contains_prob", FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled),
5990 IEEE802154_MLME_PSIE_EB_FLT_PERCENT, NULL, HFILL }},
5991
5992 { &hf_ieee802154_psie_eb_filter_percent_prob,
5993 { "Response Probability Percentage", "wpan.eb_filter.prob", FT_UINT8, BASE_DEC, NULL,
5994 0x0, NULL, HFILL }},
5995
5996 { &hf_ieee802154_psie_eb_filter_attr_id,
5997 { "Requested Attribute Length", "wpan.eb_filter.attr_id", FT_UINT8, BASE_DEC, NULL,
5998 IEEE802154_MLME_PSIE_EB_FLT_ATTR_LEN, NULL, HFILL }},
5999
6000 { &hf_ieee802154_psie_eb_filter_attr_id_bitmap,
6001 { "Attribute ID Bitmap", "wpan.eb_filter.attr_id_bits", FT_UINT24, BASE_HEX, NULL,
6002 0x0, NULL, HFILL }},
6003
6004 { &hf_ieee802154_tsch_sync,
6005 { "TSCH Synchronization IE", "wpan.tsch.time_sync", FT_NONE, BASE_NONE, NULL, 0x0,
6006 NULL, HFILL }},
6007
6008 { &hf_ieee802154_tsch_asn,
6009 { "Absolute Slot Number", "wpan.tsch.asn", FT_UINT40, BASE_DEC, NULL, 0x0,
6010 NULL, HFILL }},
6011
6012 { &hf_ieee802154_tsch_join_metric,
6013 { "Join Metric", "wpan.tsch.join_metric", FT_UINT8, BASE_DEC, NULL, 0x0,
6014 NULL, HFILL }},
6015
6016 { &hf_ieee802154_tsch_timeslot,
6017 { "TSCH Timeslot IE", "wpan.tsch.timeslot", FT_NONE, BASE_NONE, NULL, 0x0,
6018 NULL, HFILL }},
6019
6020 { &hf_ieee802154_tsch_timeslot_id,
6021 { "Timeslot ID", "wpan.tsch.timeslot.id", FT_UINT8, BASE_HEX, NULL, 0x0,
6022 "Identifier of the Timeslot Template", HFILL }},
6023
6024 { &hf_ieee802154_tsch_timeslot_cca_offset,
6025 { "CCA Offset", "wpan.tsch.timeslot.cca_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
6026 "Time between the beginning of the timeslot and the start of CCA", HFILL }},
6027
6028 { &hf_ieee802154_tsch_timeslot_cca,
6029 { "CCA", "wpan.tsch.timeslot.cca", FT_UINT16, BASE_DEC, NULL, 0x0,
6030 "Duration of CCA", HFILL }},
6031
6032 { &hf_ieee802154_tsch_timeslot_tx_offset,
6033 { "TX Offset", "wpan.tsch.timeslot.tx_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
6034 "Time between the beginning of the timeslot and the start of frame transmission", HFILL }},
6035
6036 { &hf_ieee802154_tsch_timeslot_rx_offset,
6037 { "RX Offset", "wpan.tsch.timeslot.rx_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
6038 "Time between the beginning of the timeslot to when the receiver shall be listening", HFILL }},
6039
6040 { &hf_ieee802154_tsch_timeslot_rx_ack_delay,
6041 { "RX Ack Delay", "wpan.tsch.timeslot.rx_ack_delay", FT_UINT16, BASE_DEC, NULL, 0x0,
6042 "Time between the end of frame to when the transmitter shall listen for acknowledgment", HFILL }},
6043
6044 { &hf_ieee802154_tsch_timeslot_tx_ack_delay,
6045 { "TX Ack Delay", "wpan.tsch.timeslot.tx_ack_delay", FT_UINT16, BASE_DEC, NULL, 0x0,
6046 "Time between the end of frame to start of acknowledgment", HFILL }},
6047
6048 { &hf_ieee802154_tsch_timeslot_rx_wait,
6049 { "RX Wait", "wpan.tsch.timeslot.rx_wait", FT_UINT16, BASE_DEC, NULL, 0x0,
6050 "Time to wait for the start of frame", HFILL }},
6051
6052 { &hf_ieee802154_tsch_timeslot_ack_wait,
6053 { "Ack Wait", "wpan.tsch.timeslot.ack_wait", FT_UINT16, BASE_DEC, NULL, 0x0,
6054 "Minimum time to wait for the start of an acknowledgment", HFILL }},
6055
6056 { &hf_ieee802154_tsch_timeslot_turnaround,
6057 { "Turn Around", "wpan.tsch.timeslot.turnaround", FT_UINT16, BASE_DEC, NULL, 0x0,
6058 "Transmit to receive turnaround time", HFILL }},
6059
6060 { &hf_ieee802154_tsch_timeslot_max_ack,
6061 { "Max Ack", "wpan.tsch.timeslot.max_ack", FT_UINT16, BASE_DEC, NULL, 0x0,
6062 "Transmission time to send an acknowledgment", HFILL }},
6063
6064 { &hf_ieee802154_tsch_timeslot_max_tx,
6065 { "Max TX", "wpan.tsch.timeslot.max_tx", FT_UINT24, BASE_DEC, NULL, 0x0,
6066 "Transmission time to send the maximum length frame", HFILL }},
6067
6068 { &hf_ieee802154_tsch_timeslot_length,
6069 { "Timeslot Length", "wpan.tsch.timeslot.length", FT_UINT24, BASE_DEC, NULL, 0x0,
6070 "Total length of the timeslot, including any unused time after frame transmission", HFILL }},
6071
6072 { &hf_ieee802154_tsch_channel_hopping,
6073 { "Channel Hopping IE", "wpan.channel_hopping", FT_NONE, BASE_NONE, NULL, 0x0,
6074 NULL, HFILL }},
6075
6076 { &hf_ieee802154_tsch_slotframe,
6077 { "Slotframe IE", "wpan.tsch.slotframe", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
6078
6079 { &hf_ieee802154_tsch_link_info,
6080 { "Link Information", "wpan.tsch.link_info", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
6081
6082 { &hf_ieee802154_tsch_slotf_link_nb_slotf,
6083 { "Number of Slotframes", "wpan.tsch.slotframe_num", FT_UINT8, BASE_DEC, NULL, 0x0,
6084 NULL, HFILL }},
6085
6086 { &hf_ieee802154_tsch_slotf_link_slotf_handle,
6087 { "Slotframe handle", "wpan.tsch.slotframe_handle", FT_UINT8, BASE_DEC, NULL, 0x0,
6088 NULL, HFILL }},
6089
6090 { &hf_ieee802154_tsch_slotf_size,
6091 { "Slotframe size", "wpan.tsch.slotframe_size", FT_UINT16, BASE_DEC, NULL, 0x0,
6092 NULL, HFILL }},
6093
6094 { &hf_ieee802154_tsch_slotf_link_nb_links,
6095 { "Number of Links", "wpan.tsch.nb_links", FT_UINT8, BASE_DEC, NULL, 0x0,
6096 NULL, HFILL }},
6097
6098 { &hf_ieee802154_tsch_slotf_link_timeslot,
6099 { "Timeslot", "wpan.tsch.link_timeslot", FT_UINT16, BASE_DEC, NULL, 0x0,
6100 NULL, HFILL }},
6101
6102 { &hf_ieee802154_tsch_slotf_link_channel_offset,
6103 { "Channel Offset", "wpan.tsch.channel_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
6104 NULL, HFILL }},
6105
6106 { &hf_ieee802154_tsch_slotf_link_options,
6107 { "Link Options", "wpan.tsch.link_options", FT_UINT8, BASE_HEX, NULL, 0x0,
6108 NULL, HFILL }},
6109
6110 { &hf_ieee802154_tsch_slotf_link_options_tx,
6111 { "TX Link", "wpan.tsch.link_options.tx", FT_BOOLEAN, 8, NULL, (1 << 0),
6112 NULL, HFILL }},
6113
6114 { &hf_ieee802154_tsch_slotf_link_options_rx,
6115 { "RX Link", "wpan.tsch.link_options.rx", FT_BOOLEAN, 8, NULL, (1 << 1),
6116 NULL, HFILL }},
6117
6118 { &hf_ieee802154_tsch_slotf_link_options_shared,
6119 { "Shared Link", "wpan.tsch.link_options.shared", FT_BOOLEAN, 8, NULL, (1 << 2),
6120 NULL, HFILL }},
6121
6122 { &hf_ieee802154_tsch_slotf_link_options_timkeeping,
6123 { "Timekeeping", "wpan.tsch.link_options.timekeeping", FT_BOOLEAN, 8, NULL, (1 << 3),
6124 NULL, HFILL }},
6125
6126 { &hf_ieee802154_tsch_slotf_link_options_priority,
6127 { "Priority", "wpan.tsch.link_options.priority", FT_BOOLEAN, 8, NULL, (1 << 4),
6128 NULL, HFILL }},
6129
6130 { &hf_ieee802154_tsch_hopping_sequence_id,
6131 { "Hopping Sequence ID", "wpan.tsch.hopping_sequence_id", FT_UINT8, BASE_HEX, NULL, 0x0,
6132 NULL, HFILL }},
6133
6134 /* IETF IE */
6135 { &hf_ieee802154_pie_ietf,
6136 { "IETF Payload IE", "wpan.payload_ie.ietf", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
6137
6138 { &hf_ieee802154_p_ie_ietf_sub_id,
6139 { "Sub-ID", "wpan.ietf_ie.sub_id", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
6140
6141 /* IETF IE - 6top IE */
6142 { &hf_ieee802154_6top,
6143 { "6top IE", "wpan.6top", FT_NONE, BASE_NONE, NULL, 0x0,
6144 NULL, HFILL }},
6145
6146 { &hf_ieee802154_6top_version,
6147 { "6P Version", "wpan.6top_version", FT_UINT8, BASE_DEC, NULL, IETF_6TOP_VERSION,
6148 NULL, HFILL }},
6149
6150 { &hf_ieee802154_6top_type,
6151 { "Type", "wpan.6top_type", FT_UINT8, BASE_HEX, VALS(ietf_6top_types), IETF_6TOP_TYPE,
6152 NULL, HFILL }},
6153
6154 { &hf_ieee802154_6top_flags_reserved,
6155 { "Reserved", "wpan.6top_flags_reserved", FT_UINT8, BASE_HEX, NULL, IETF_6TOP_FLAGS_RESERVED,
6156 NULL, HFILL }},
6157
6158 { &hf_ieee802154_6top_code,
6159 { "Code", "wpan.6top_code", FT_UINT8, BASE_HEX, NULL, 0x0,
6160 NULL, HFILL }},
6161
6162 { &hf_ieee802154_6top_sfid,
6163 { "SFID (6top Scheduling Function ID)", "wpan.6top_sfid", FT_UINT8, BASE_HEX, NULL, 0x0,
6164 NULL, HFILL }},
6165
6166 { &hf_ieee802154_6top_seqnum,
6167 { "SeqNum", "wpan.6top_seqnum", FT_UINT8, BASE_DEC, NULL, IETF_6TOP_SEQNUM,
6168 NULL, HFILL }},
6169
6170 { &hf_ieee802154_6top_metadata,
6171 { "Metadata", "wpan.6top_metadata", FT_UINT16, BASE_HEX, NULL, 0x0,
6172 NULL, HFILL }},
6173
6174 { &hf_ieee802154_6top_cell_options,
6175 { "Cell Options", "wpan.6top_cell_options", FT_UINT8, BASE_HEX, VALS(ietf_6top_cell_options), 0x0,
6176 NULL, HFILL }},
6177
6178 { &hf_ieee802154_6top_cell_option_tx,
6179 { "Transmit (TX) Cell", "wpan.6top_cell_option_tx", FT_UINT8, BASE_HEX, NULL, IETF_6TOP_CELL_OPTION_TX,
6180 NULL, HFILL }},
6181
6182 { &hf_ieee802154_6top_cell_option_rx,
6183 { "Receive (RX) Cell", "wpan.6top_cell_option_rx", FT_UINT8, BASE_HEX, NULL, IETF_6TOP_CELL_OPTION_RX,
6184 NULL, HFILL }},
6185
6186 { &hf_ieee802154_6top_cell_option_shared,
6187 { "SHARED Cell", "wpan.6top_cell_option_shared", FT_UINT8, BASE_HEX, NULL, IETF_6TOP_CELL_OPTION_SHARED,
6188 NULL, HFILL }},
6189
6190 { &hf_ieee802154_6top_cell_option_reserved,
6191 { "Reserved", "wpan.6top_cell_option_reserved", FT_UINT8, BASE_HEX, NULL, IETF_6TOP_CELL_OPTION_RESERVED,
6192 NULL, HFILL }},
6193
6194 { &hf_ieee802154_6top_num_cells,
6195 { "Number of Cells", "wpan.6top_num_cells", FT_UINT8, BASE_DEC, NULL, 0x0,
6196 NULL, HFILL }},
6197
6198 { &hf_ieee802154_6top_cell_list,
6199 { "CellList", "wpan.6top_cell_list", FT_NONE, BASE_NONE, NULL, 0x0,
6200 NULL, HFILL }},
6201
6202 { &hf_ieee802154_6top_rel_cell_list,
6203 { "Rel. CellList", "wpan.6top_rel_cell_list", FT_NONE, BASE_NONE, NULL, 0x0,
6204 NULL, HFILL }},
6205
6206 { &hf_ieee802154_6top_cand_cell_list,
6207 { "Cand. CellList", "wpan.6top_cand_cell_list", FT_NONE, BASE_NONE, NULL, 0x0,
6208 NULL, HFILL }},
6209
6210 { &hf_ieee802154_6top_cell,
6211 { "Cell", "wpan.6top_cell", FT_BYTES, BASE_NONE, NULL, 0x0,
6212 NULL, HFILL }},
6213
6214 { &hf_ieee802154_6top_reserved,
6215 { "Reserved", "wpan.6top_reserved", FT_UINT8, BASE_HEX, NULL, 0x0,
6216 NULL, HFILL }},
6217
6218 { &hf_ieee802154_6top_offset,
6219 { "Offset", "wpan.6top_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
6220 NULL, HFILL }},
6221
6222 { &hf_ieee802154_6top_max_num_cells,
6223 { "Maximum Number of Requested Cells", "wpan.6top_max_num_cells", FT_UINT16, BASE_DEC, NULL, 0x0,
6224 NULL, HFILL }},
6225
6226 { &hf_ieee802154_6top_slot_offset,
6227 { "Slot Offset", "wpan.6top_cell_slot_offset", FT_UINT16, BASE_HEX, NULL, 0x0,
6228 NULL, HFILL }},
6229
6230 { &hf_ieee802154_6top_channel_offset,
6231 { "Channel Offset", "wpan.6top_channel_offset", FT_UINT16, BASE_HEX, NULL, 0x0,
6232 NULL, HFILL }},
6233
6234 { &hf_ieee802154_6top_total_num_cells,
6235 { "Total Number of Cells", "wpan.6top_total_num_cells", FT_UINT16, BASE_DEC, NULL, 0x0,
6236 NULL, HFILL }},
6237
6238 { &hf_ieee802154_6top_payload,
6239 { "Payload", "wpan.6top_payload", FT_BYTES, BASE_NONE, NULL, 0x0,
6240 NULL, HFILL }},
6241
6242 /* MPX IE (IEEE 802.15.9) */
6243 { &hf_ieee802159_mpx,
6244 { "MPX IE", "wpan.mpx", FT_NONE, BASE_NONE, NULL, 0x0,
6245 NULL, HFILL }
6246 },
6247
6248 { &hf_ieee802159_mpx_transaction_control,
6249 { "Transaction Control", "wpan.mpx.transaction_control", FT_UINT8, BASE_HEX, NULL, 0x0,
6250 NULL, HFILL }
6251 },
6252
6253 { &hf_ieee802159_mpx_transfer_type,
6254 { "Transfer Type", "wpan.mpx.transfer_type", FT_UINT8, BASE_HEX, VALS(mpx_transfer_type_vals), IEEE802159_MPX_TRANSFER_TYPE_MASK,
6255 NULL, HFILL }
6256 },
6257
6258 { &hf_ieee802159_mpx_transaction_id,
6259 { "Transaction ID", "wpan.mpx.transaction_id", FT_UINT8, BASE_HEX, NULL, IEEE802159_MPX_TRANSACTION_ID_MASK,
6260 NULL, HFILL }
6261 },
6262
6263 { &hf_ieee802159_mpx_transaction_id_as_multiplex_id,
6264 { "Multiplex ID", "wpan.mpx.multiplex_id", FT_UINT8, BASE_HEX, VALS(mpx_multiplex_id_vals), IEEE802159_MPX_TRANSACTION_ID_MASK,
6265 "Transaction ID used as Multiplex ID", HFILL }
6266 },
6267
6268 { &hf_ieee802159_mpx_fragment_number,
6269 { "Fragment Number", "wpan.mpx.fragment_number", FT_UINT8, BASE_DEC, NULL, 0x0,
6270 NULL, HFILL }
6271 },
6272
6273 { &hf_ieee802159_mpx_total_frame_size,
6274 { "Total Frame Size", "wpan.mpx.total_frame_size", FT_UINT16, BASE_DEC, NULL, 0x0,
6275 "Total Upper-Layer Frame Size", HFILL }
6276 },
6277
6278 { &hf_ieee802159_mpx_multiplex_id,
6279 { "Multiplex ID", "wpan.mpx.multiplex_id", FT_UINT16, BASE_HEX, NULL, 0x0,
6280 NULL, HFILL }
6281 },
6282
6283 { &hf_ieee802159_mpx_kmp_id,
6284 { "KMP ID", "wpan.mpx.kmp.id", FT_UINT8, BASE_DEC, VALS(ieee802154_mpx_kmp_id_vals), 0x0,
6285 NULL, HFILL }
6286 },
6287
6288 { &hf_ieee802159_mpx_kmp_vendor_oui,
6289 { "Vendor OUI", "wpan.mpx.kmp.vendor_oui", FT_UINT24, BASE_OUI, NULL, 0x0,
6290 NULL, HFILL }
6291 },
6292
6293 { &hf_ieee802159_mpx_fragment,
6294 { "Upper-Layer Frame Fragment", "wpan.mpx.fragment", FT_BYTES, SEP_SPACE, NULL, 0x0,
6295 NULL, HFILL }
6296 },
6297
6298 { &hf_ieee802159_mpx_wisun_subid,
6299 { "Wi-SUN Multiplex Sub ID", "wpan.mpx.wisun", FT_UINT8, BASE_HEX, VALS(mpx_wisun_subid_vals), 0x0,
6300 NULL, HFILL }
6301 },
6302
6303 /* Command Frame Specific Fields */
6304
6305 { &hf_ieee802154_cmd_id,
6306 { "Command Identifier", "wpan.cmd", FT_UINT8, BASE_HEX, VALS(ieee802154_cmd_names), 0x0,
6307 NULL, HFILL }},
6308
6309 { &hf_ieee802154_cmd_vendor_oui,
6310 { "Vendor OUI", "wpan.cmd.vendor_oui", FT_UINT24, BASE_OUI, NULL, 0x0,
6311 NULL, HFILL }},
6312
6313 /* Capability Information Fields */
6314
6315 { &hf_ieee802154_cinfo_alt_coord,
6316 { "Alternate PAN Coordinator", "wpan.cinfo.alt_coord", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_ALT_PAN_COORD,
6317 "Whether this device can act as a PAN coordinator or not.", HFILL }},
6318
6319 { &hf_ieee802154_cinfo_device_type,
6320 { "Device Type", "wpan.cinfo.device_type", FT_BOOLEAN, 8, TFS(&tfs_cinfo_device_type), IEEE802154_CMD_CINFO_DEVICE_TYPE,
6321 "Whether this device is RFD (reduced-function device) or FFD (full-function device).", HFILL }},
6322
6323 { &hf_ieee802154_cinfo_power_src,
6324 { "Power Source", "wpan.cinfo.power_src", FT_BOOLEAN, 8, TFS(&tfs_cinfo_power_src), IEEE802154_CMD_CINFO_POWER_SRC,
6325 "Whether this device is operating on AC/mains or battery power.", HFILL }},
6326
6327 { &hf_ieee802154_cinfo_idle_rx,
6328 { "Receive On When Idle", "wpan.cinfo.idle_rx", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_IDLE_RX,
6329 "Whether this device can receive packets while idle or not.", HFILL }},
6330
6331 { &hf_ieee802154_cinfo_sec_capable,
6332 { "Security Capability", "wpan.cinfo.sec_capable", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_SEC_CAPABLE,
6333 "Whether this device is capable of receiving encrypted packets.", HFILL }},
6334
6335 { &hf_ieee802154_cinfo_alloc_addr,
6336 { "Allocate Address", "wpan.cinfo.alloc_addr", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_ALLOC_ADDR,
6337 "Whether this device wishes to use a 16-bit short address instead of its IEEE 802.15.4 64-bit long address.", HFILL }},
6338
6339 /* Association response fields */
6340
6341 { &hf_ieee802154_assoc_addr,
6342 { "Short Address", "wpan.asoc.addr", FT_UINT16, BASE_HEX, NULL, 0x0,
6343 "The short address that the device should assume. An address of 0xfffe indicates that the device should use its IEEE 64-bit long address.", HFILL }},
6344
6345 { &hf_ieee802154_assoc_status,
6346 { "Association Status", "wpan.assoc.status", FT_UINT8, BASE_HEX, NULL, 0x0,
6347 NULL, HFILL }},
6348
6349 { &hf_ieee802154_disassoc_reason,
6350 { "Disassociation Reason", "wpan.disassoc.reason", FT_UINT8, BASE_HEX, NULL, 0x0,
6351 NULL, HFILL }},
6352
6353 /* Coordinator Realignment fields */
6354
6355 { &hf_ieee802154_realign_pan,
6356 { "PAN ID", "wpan.realign.pan", FT_UINT16, BASE_HEX, NULL, 0x0,
6357 "The PAN identifier the coordinator wishes to use for future communication.", HFILL }},
6358
6359 { &hf_ieee802154_realign_caddr,
6360 { "Coordinator Short Address", "wpan.realign.addr", FT_UINT16, BASE_HEX, NULL, 0x0,
6361 "The 16-bit address the coordinator wishes to use for future communication.", HFILL }},
6362
6363 { &hf_ieee802154_realign_channel,
6364 { "Logical Channel", "wpan.realign.channel", FT_UINT8, BASE_DEC, NULL, 0x0,
6365 "The logical channel the coordinator wishes to use for future communication.", HFILL }},
6366
6367 { &hf_ieee802154_realign_addr,
6368 { "Short Address", "wpan.realign.addr", FT_UINT16, BASE_HEX, NULL, 0x0,
6369 "A short-address that the orphaned device shall assume if applicable.", HFILL }},
6370
6371 { &hf_ieee802154_realign_channel_page,
6372 { "Channel Page", "wpan.realign.channel_page", FT_UINT8, BASE_DEC, NULL, 0x0,
6373 "The logical channel page the coordinator wishes to use for future communication.", HFILL }},
6374
6375 { &hf_ieee802154_gtsreq_len,
6376 { "GTS Length", "wpan.gtsreq.length", FT_UINT8, BASE_DEC, NULL, IEEE802154_CMD_GTS_REQ_LEN,
6377 "Number of superframe slots the device is requesting.", HFILL }},
6378
6379 { &hf_ieee802154_gtsreq_dir,
6380 { "GTS Direction", "wpan.gtsreq.direction", FT_BOOLEAN, 8, TFS(&tfs_gtsreq_dir), IEEE802154_CMD_GTS_REQ_DIR,
6381 "The direction of traffic in the guaranteed timeslot.", HFILL }},
6382
6383 { &hf_ieee802154_gtsreq_type,
6384 { "Characteristic Type", "wpan.gtsreq.type", FT_BOOLEAN, 8, TFS(&tfs_gtsreq_type), IEEE802154_CMD_GTS_REQ_TYPE,
6385 "Whether this request is to allocate or deallocate a timeslot.", HFILL }},
6386
6387 /* Beacon Frame Specific Fields */
6388
6389 { &hf_ieee802154_beacon_order,
6390 { "Beacon Interval", "wpan.beacon_order", FT_UINT16, BASE_DEC, NULL, IEEE802154_BEACON_ORDER_MASK,
6391 "Specifies the transmission interval of the beacons.", HFILL }},
6392
6393 { &hf_ieee802154_superframe_order,
6394 { "Superframe Interval", "wpan.superframe_order", FT_UINT16, BASE_DEC, NULL,
6395 IEEE802154_SUPERFRAME_ORDER_MASK,
6396 "Specifies the length of time the coordinator will interact with the PAN.", HFILL }},
6397
6398 { &hf_ieee802154_cap,
6399 { "Final CAP Slot", "wpan.cap", FT_UINT16, BASE_DEC, NULL, IEEE802154_SUPERFRAME_CAP_MASK,
6400 "Specifies the final superframe slot used by the CAP.", HFILL }},
6401
6402 { &hf_ieee802154_superframe_battery_ext,
6403 { "Battery Extension", "wpan.battery_ext", FT_BOOLEAN, 16, NULL, IEEE802154_BATT_EXTENSION_MASK,
6404 "Whether transmissions may not extend past the length of the beacon frame.", HFILL }},
6405
6406 { &hf_ieee802154_superframe_coord,
6407 { "PAN Coordinator", "wpan.bcn_coord", FT_BOOLEAN, 16, NULL, IEEE802154_SUPERFRAME_COORD_MASK,
6408 "Whether this beacon frame is being transmitted by the PAN coordinator or not.", HFILL }},
6409
6410 { &hf_ieee802154_assoc_permit,
6411 { "Association Permit", "wpan.assoc_permit", FT_BOOLEAN, 16, NULL, IEEE802154_ASSOC_PERMIT_MASK,
6412 "Whether this PAN is accepting association requests or not.", HFILL }},
6413
6414 { &hf_ieee802154_gts_count,
6415 { "GTS Descriptor Count", "wpan.gts.count", FT_UINT8, BASE_DEC, NULL, 0x0,
6416 "The number of GTS descriptors present in this beacon frame.", HFILL }},
6417
6418 { &hf_ieee802154_gts_permit,
6419 { "GTS Permit", "wpan.gts.permit", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
6420 "Whether the PAN coordinator is accepting GTS requests or not.", HFILL }},
6421
6422 { &hf_ieee802154_gts_direction,
6423 { "Direction", "wpan.gts.direction", FT_BOOLEAN, BASE_NONE, TFS(&ieee802154_gts_direction_tfs), 0x0,
6424 "A flag defining the direction of the GTS Slot.", HFILL }},
6425
6426 { &hf_ieee802154_gts_address,
6427 { "Address", "wpan.gts.address", FT_UINT16, BASE_HEX, NULL, 0x0,
6428 NULL, HFILL }},
6429
6430 { &hf_ieee802154_pending16,
6431 { "Address", "wpan.pending16", FT_UINT16, BASE_HEX, NULL, 0x0,
6432 "Device with pending data to receive.", HFILL }},
6433
6434 { &hf_ieee802154_pending64,
6435 { "Address", "wpan.pending64", FT_EUI64, BASE_NONE, NULL, 0x0,
6436 "Device with pending data to receive.", HFILL }},
6437
6438 /* Auxiliary Security Header Fields */
6439 { &hf_ieee802154_aux_security_header,
6440 { "Auxiliary Security Header", "wpan.aux_sec.hdr", FT_NONE, BASE_NONE, NULL,
6441 0x0, "The Auxiliary Security Header of the frame", HFILL }},
6442
6443 { &hf_ieee802154_aux_sec_security_level,
6444 { "Security Level", "wpan.aux_sec.sec_level", FT_UINT8, BASE_HEX, VALS(ieee802154_sec_level_names),
6445 IEEE802154_AUX_SEC_LEVEL_MASK, "The Security Level of the frame", HFILL }},
6446
6447 { &hf_ieee802154_aux_sec_security_control,
6448 { "Security Control Field", "wpan.aux_sec.security_control_field", FT_UINT8, BASE_HEX, NULL,
6449 0x0, NULL, HFILL }},
6450
6451 { &hf_ieee802154_aux_sec_key_id_mode,
6452 { "Key Identifier Mode", "wpan.aux_sec.key_id_mode", FT_UINT8, BASE_HEX, VALS(ieee802154_key_id_mode_names),
6453 IEEE802154_AUX_KEY_ID_MODE_MASK,
6454 "The scheme to use by the recipient to lookup the key in its key table", HFILL }},
6455
6456 { &hf_ieee802154_aux_sec_frame_counter_suppression,
6457 { "Frame Counter Suppression", "wpan.aux_sec.frame_counter_suppression", FT_BOOLEAN, 8, NULL,
6458 IEEE802154_AUX_FRAME_COUNTER_SUPPRESSION_MASK,
6459 "Whether the frame counter is omitted from the Auxiliary Security Header", HFILL }},
6460
6461 { &hf_ieee802154_aux_sec_asn_in_nonce,
6462 { "ASN in Nonce", "wpan.aux_sec.asn_in_nonce", FT_BOOLEAN, 8, NULL,
6463 IEEE802154_AUX_ASN_IN_NONCE_MASK,
6464 "Whether the ASN is used to generate the nonce instead of the frame counter", HFILL }},
6465
6466 { &hf_ieee802154_aux_sec_reserved,
6467 { "Reserved", "wpan.aux_sec.reserved", FT_UINT8, BASE_HEX, NULL, IEEE802154_AUX_CTRL_RESERVED_MASK,
6468 NULL, HFILL }},
6469
6470 { &hf_ieee802154_aux_sec_frame_counter,
6471 { "Frame Counter", "wpan.aux_sec.frame_counter", FT_UINT32, BASE_DEC, NULL, 0x0,
6472 "Frame counter of the originator of the protected frame", HFILL }},
6473
6474 { &hf_ieee802154_aux_sec_key_source,
6475 { "Key Source", "wpan.aux_sec.key_source", FT_UINT64, BASE_HEX, NULL, 0x0,
6476 "Key Source for processing of the protected frame", HFILL }},
6477
6478 { &hf_ieee802154_aux_sec_key_source_bytes,
6479 { "Key Source", "wpan.aux_sec.key_source.bytes", FT_BYTES, BASE_NONE, NULL, 0x0,
6480 "Key Source for processing of the protected frame", HFILL }},
6481
6482 { &hf_ieee802154_aux_sec_key_index,
6483 { "Key Index", "wpan.aux_sec.key_index", FT_UINT8, BASE_HEX, NULL, 0x0,
6484 "Key Index for processing of the protected frame", HFILL }},
6485
6486 { &hf_ieee802154_mic,
6487 { "MIC", "wpan.mic", FT_BYTES, BASE_NONE, NULL, 0x0,
6488 NULL, HFILL }},
6489
6490 { &hf_ieee802154_key_number,
6491 { "Key Number", "wpan.key_number", FT_UINT8, BASE_DEC, NULL, 0x0,
6492 "Key number used to decode", HFILL }},
6493
6494 /* IEEE 802.15.4-2003 Security Header Fields */
6495 { &hf_ieee802154_sec_frame_counter,
6496 { "Frame Counter", "wpan.sec_frame_counter", FT_UINT32, BASE_HEX, NULL, 0x0,
6497 "Frame counter of the originator of the protected frame (802.15.4-2003)", HFILL }},
6498
6499 { &hf_ieee802154_sec_key_sequence_counter,
6500 { "Key Sequence Counter", "wpan.sec_key_sequence_counter", FT_UINT8, BASE_HEX, NULL, 0x0,
6501 "Key Sequence counter of the originator of the protected frame (802.15.4-2003)", HFILL }},
6502
6503 { &hf_ieee802154_no_ack,
6504 { "No ack found", "wpan.no_ack", FT_NONE, BASE_NONE, NULL, 0x0,
6505 "No corresponding ack frame was found", HFILL }},
6506
6507 { &hf_ieee802154_no_ack_request,
6508 { "No request found", "wpan.no_ack_request", FT_NONE, BASE_NONE, NULL, 0x0,
6509 "No corresponding request frame was found", HFILL }},
6510
6511 { &hf_ieee802154_ack_in,
6512 { "Ack In", "wpan.ack_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
6513 "The ack to this request is in this frame", HFILL }},
6514
6515 { &hf_ieee802154_ack_to,
6516 { "Ack To", "wpan.ack_to", FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_ACK), 0x0,
6517 "This is the ack to the request in this frame", HFILL }},
6518
6519 { &hf_ieee802154_ack_time,
6520 { "Ack Time", "wpan.ack_time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
6521 "The time between the request and the ack", HFILL }},
6522
6523 /* ZBOSS dump */
6524
6525 { &hf_zboss_page,
6526 { "Page", "wpan-zboss.page", FT_UINT8, BASE_DEC_HEX, VALS(zboss_page_names), 0xFE,
6527 "IEEE802.15.4 page number", HFILL } },
6528
6529 { &hf_zboss_channel,
6530 { "Channel", "wpan-zboss.channel", FT_UINT8, BASE_DEC, NULL, 0x0,
6531 "Channel number", HFILL }},
6532
6533 { &hf_zboss_direction,
6534 { "ZBOSS Direction", "wpan-zboss.direction", FT_UINT8, BASE_HEX, VALS(zboss_direction_names), 0x01,
6535 "ZBOSS Packet Direction", HFILL }},
6536
6537 { &hf_zboss_trace_number,
6538 { "Trace number", "wpan-zboss.trace", FT_UINT32, BASE_DEC, NULL, 0x0,
6539 "Trace item number", HFILL }},
6540
6541 /* TAP Packet Fields */
6542 { &hf_ieee802154_tap_version,
6543 { "Version", "wpan-tap.version", FT_UINT8, BASE_DEC, NULL, 0x0,
6544 "TAP Packet Version", HFILL }},
6545
6546 { &hf_ieee802154_tap_reserved,
6547 { "Reserved", "wpan-tap.reserved", FT_UINT8, BASE_DEC, NULL, 0x0,
6548 "TAP Packet Reserved", HFILL }},
6549
6550 { &hf_ieee802154_tap_length,
6551 { "Length", "wpan-tap.length", FT_UINT16, BASE_DEC, NULL, 0x0,
6552 "TAP Packet Length", HFILL }},
6553
6554 { &hf_ieee802154_tap_data_length,
6555 { "Data Length", "wpan-tap.data_length", FT_UINT16, BASE_DEC, NULL, 0x0,
6556 "IEEE 802.15.4 Data Length", HFILL }},
6557
6558 { &hf_ieee802154_tap_tlv_type,
6559 { "TLV Type", "wpan-tap.tlv.type", FT_UINT16, BASE_DEC, VALS(tap_tlv_types), 0x0,
6560 NULL, HFILL }},
6561
6562 { &hf_ieee802154_tap_tlv_length,
6563 { "TLV Length", "wpan-tap.tlv.length", FT_UINT16, BASE_DEC, NULL, 0x0,
6564 NULL, HFILL }},
6565
6566 { &hf_ieee802154_tap_tlv_unknown,
6567 { "Unknown", "wpan-tap.tlv.unknown", FT_BYTES, BASE_NONE, NULL, 0x0,
6568 NULL, HFILL }},
6569
6570 { &hf_ieee802154_tap_tlv_padding,
6571 { "Padding", "wpan-tap.tlv.padding", FT_BYTES, BASE_NONE, NULL, 0x0,
6572 NULL, HFILL }},
6573
6574 { &hf_ieee802154_tap_fcs_type,
6575 { "FCS Type", "wpan-tap.fcs_type", FT_UINT8, BASE_DEC, VALS(tap_fcs_type_names), 0x0,
6576 NULL, HFILL }},
6577
6578 { &hf_ieee802154_tap_rss,
6579 { "RSS", "wpan-tap.rss", FT_FLOAT, BASE_FLOAT|BASE_UNIT_STRING, &units_dbm, 0x0,
6580 NULL, HFILL }},
6581
6582 { &hf_ieee802154_ch_num,
6583 { "Channel", "wpan-tap.ch_num", FT_UINT16, BASE_DEC, NULL, 0x0,
6584 "Channel number", HFILL }},
6585
6586 { &hf_ieee802154_ch_page,
6587 { "Page", "wpan-tap.ch_page", FT_UINT8, BASE_DEC, VALS(channel_page_names), 0x0,
6588 "Channel page", HFILL }},
6589
6590 { &hf_ieee802154_bit_rate,
6591 { "Bit Rate", "wpan-tap.bit_rate", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, &units_bit_sec, 0x0,
6592 NULL, HFILL }},
6593
6594 { &hf_ieee802154_sun_band,
6595 { "Band", "wpan-tap.sun_band", FT_UINT8, BASE_DEC, VALS(sun_bands), 0x0,
6596 NULL, HFILL }},
6597
6598 { &hf_ieee802154_sun_type,
6599 { "Type", "wpan-tap.sun_type", FT_UINT8, BASE_DEC, VALS(sun_types), 0x0,
6600 NULL, HFILL }},
6601
6602 { &hf_ieee802154_sun_mode,
6603 { "Mode", "wpan-tap.sun_mode", FT_UINT8, BASE_DEC, NULL, 0x0,
6604 NULL, HFILL }},
6605
6606 { &hf_ieee802154_mode_fsk_a,
6607 { "FSK-A mode", "wpan-tap.mode.fsk_a", FT_UINT8, BASE_DEC, VALS(fsk_a_modes), 0x0,
6608 NULL, HFILL }},
6609
6610 { &hf_ieee802154_mode_fsk_b,
6611 { "FSK-B mode", "wpan-tap.mode.fsk_b", FT_UINT8, BASE_DEC, VALS(fsk_b_modes), 0x0,
6612 NULL, HFILL }},
6613
6614 { &hf_ieee802154_mode_oqpsk_a,
6615 { "O-QPSK-A mode", "wpan-tap.mode.oqpsk_a", FT_UINT8, BASE_DEC, VALS(oqpsk_a_modes), 0x0,
6616 NULL, HFILL }},
6617
6618 { &hf_ieee802154_mode_oqpsk_b,
6619 { "O-QPSK-B mode", "wpan-tap.mode.oqpsk_b", FT_UINT8, BASE_DEC, VALS(oqpsk_b_modes), 0x0,
6620 NULL, HFILL }},
6621
6622 { &hf_ieee802154_mode_oqpsk_c,
6623 { "O-QPSK-C mode", "wpan-tap.mode.oqpsk_c", FT_UINT8, BASE_DEC, VALS(oqpsk_c_modes), 0x0,
6624 NULL, HFILL }},
6625
6626 { &hf_ieee802154_mode_ofdm,
6627 { "OFDM mode", "wpan-tap.mode.ofdm", FT_UINT8, BASE_DEC, VALS(ofdm_modes), 0x0,
6628 NULL, HFILL }},
6629
6630 { &hf_ieee802154_sof_ts,
6631 { "Start of frame timestamp", "wpan-tap.sof_ts", FT_UINT64, BASE_DEC|BASE_UNIT_STRING, &units_nanoseconds, 0x0,
6632 NULL, HFILL }},
6633
6634 { &hf_ieee802154_eof_ts,
6635 { "End of frame timestamp", "wpan-tap.eof_ts", FT_UINT64, BASE_DEC|BASE_UNIT_STRING, &units_nanoseconds, 0x0,
6636 NULL, HFILL }},
6637
6638 { &hf_ieee802154_slot_start_ts,
6639 { "Start of slot timestamp", "wpan-tap.slot_start_ts", FT_UINT64, BASE_DEC|BASE_UNIT_STRING, &units_nanoseconds, 0x0,
6640 NULL, HFILL }},
6641
6642 { &hf_ieee802154_tap_timeslot_length,
6643 { "Timeslot length", "wpan-tap.timeslot_length", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, &units_microseconds, 0x0,
6644 NULL, HFILL }},
6645
6646 { &hf_ieee802154_tap_lqi,
6647 { "Link Quality Indicator", "wpan-tap.lqi", FT_UINT8, BASE_DEC, NULL, 0x0,
6648 NULL, HFILL }},
6649
6650 { &hf_ieee802154_chplan_start,
6651 { "Channel0 freq", "wpan-tap.chplan.start", FT_FLOAT, BASE_FLOAT|BASE_UNIT_STRING, &units_khz, 0x0,
6652 "Channel 0 center frequency", HFILL }},
6653
6654 { &hf_ieee802154_chplan_spacing,
6655 { "Spacing", "wpan-tap.chplan.spacing", FT_FLOAT, BASE_FLOAT|BASE_UNIT_STRING, &units_khz, 0x0,
6656 "Channel spacing", HFILL }},
6657
6658 { &hf_ieee802154_chplan_channels,
6659 { "Channels", "wpan-tap.chplan.channels", FT_UINT16, BASE_DEC, NULL, 0x0,
6660 "Number of channels", HFILL }},
6661
6662 { &hf_ieee802154_ch_freq,
6663 { "Frequency", "wpan-tap.ch_freq", FT_FLOAT, BASE_FLOAT|BASE_UNIT_STRING, &units_khz, 0x0,
6664 "Channel center frequency", HFILL }},
6665
6666 { &hf_ieee802154_frame_start_offset,
6667 { "Frame start offset", "wpan.tsch.frame_start_offset", FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, &units_microseconds, 0x0,
6668 "Start of frame timestamp - start of slot timestamp", HFILL }},
6669
6670 { &hf_ieee802154_frame_duration,
6671 { "Frame duration", "wpan.tsch.frame_duration", FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, &units_microseconds, 0x0,
6672 "End of frame timestamp - start of frame timestamp", HFILL }},
6673
6674 { &hf_ieee802154_frame_end_offset,
6675 { "Frame end offset", "wpan.tsch.frame_end_offset", FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, &units_microseconds, 0x0,
6676 "End of frame timestamp - (start of slot timestamp + timeslot length)", HFILL }},
6677
6678 { &hf_ieee802154_asn,
6679 { "ASN", "wpan-tap.asn", FT_UINT64, BASE_DEC, NULL, 0x0,
6680 "Absolute Slot Number", HFILL }},
6681
6682 };
6683
6684 /* Subtrees */
6685 static gint *ett[] = {
6686 &ett_ieee802154_nonask_phy,
6687 &ett_ieee802154_nonask_phy_phr,
6688 &ett_ieee802154_tap,
6689 &ett_ieee802154_tap_header,
6690 &ett_ieee802154_tap_tlv,
6691 &ett_ieee802154,
6692 &ett_ieee802154_fcf,
6693 &ett_ieee802154_auxiliary_security,
6694 &ett_ieee802154_aux_sec_control,
6695 &ett_ieee802154_aux_sec_key_id,
6696 &ett_ieee802154_fcs,
6697 &ett_ieee802154_cmd,
6698 &ett_ieee802154_superframe,
6699 &ett_ieee802154_gts,
6700 &ett_ieee802154_gts_direction,
6701 &ett_ieee802154_gts_descriptors,
6702 &ett_ieee802154_pendaddr,
6703 &ett_ieee802154_header_ies,
6704 &ett_ieee802154_header_ie,
6705 &ett_ieee802154_header_ie_tlv,
6706 &ett_ieee802154_hie_unsupported,
6707 &ett_ieee802154_hie_time_correction,
6708 &ett_ieee802154_hie_ht,
6709 &ett_ieee802154_hie_csl,
6710 &ett_ieee802154_hie_global_time,
6711 &ett_ieee802154_hie_vendor_specific,
6712 &ett_ieee802154_payload_ie,
6713 &ett_ieee802154_payload_ie_tlv,
6714 &ett_ieee802154_pie_termination,
6715 &ett_ieee802154_pie_vendor,
6716 &ett_ieee802159_mpx,
6717 &ett_ieee802159_mpx_transaction_control,
6718 &ett_ieee802154_pie_ietf,
6719 &ett_ieee802154_pie_unsupported,
6720 &ett_ieee802154_tsch_slotframe,
6721 &ett_ieee802154_tsch_slotframe_list,
6722 &ett_ieee802154_tsch_slotframe_link,
6723 &ett_ieee802154_tsch_slotframe_link_options,
6724 &ett_ieee802154_tsch_timeslot,
6725 &ett_ieee802154_tsch_synch,
6726 &ett_ieee802154_channel_hopping,
6727 &ett_ieee802154_mlme,
6728 &ett_ieee802154_mlme_payload,
6729 &ett_ieee802154_mlme_payload_data,
6730 &ett_ieee802154_mlme_unsupported,
6731 &ett_ieee802154_psie,
6732 &ett_ieee802154_eb_filter,
6733 &ett_ieee802154_eb_filter_bitmap,
6734 &ett_ieee802154_zigbee,
6735 &ett_ieee802154_zboss,
6736 &ett_ieee802154_p_ie_6top,
6737 &ett_ieee802154_p_ie_6top_cell_options,
6738 &ett_ieee802154_p_ie_6top_cell_list,
6739 &ett_ieee802154_p_ie_6top_rel_cell_list,
6740 &ett_ieee802154_p_ie_6top_cand_cell_list,
6741 &ett_ieee802154_p_ie_6top_cell
6742 };
6743
6744 static ei_register_info ei[] = {
6745 { &ei_ieee802154_fcs_bitmask_len, { "wpan.bitmask_len_error", PI_UNDECODED, PI_WARN,
6746 "Only least-significant bytes decoded", EXPFILL }},
6747 { &ei_ieee802154_invalid_addressing, { "wpan.invalid_addressing", PI_MALFORMED, PI_WARN,
6748 "Invalid Addressing", EXPFILL }},
6749 { &ei_ieee802154_invalid_panid_compression, { "wpan.invalid_panid_compression", PI_MALFORMED, PI_ERROR,
6750 "Invalid Setting for PAN ID Compression", EXPFILL }},
6751 { &ei_ieee802154_invalid_panid_compression2, { "wpan.invalid_panid_compression", PI_MALFORMED, PI_ERROR,
6752 "Invalid Pan ID Compression and addressing combination for Frame Version 2", EXPFILL }},
6753 { &ei_ieee802154_dst, { "wpan.dst_invalid", PI_MALFORMED, PI_ERROR,
6754 "Invalid Destination Address Mode", EXPFILL }},
6755 { &ei_ieee802154_src, { "wpan.src_invalid", PI_MALFORMED, PI_ERROR,
6756 "Invalid Source Address Mode", EXPFILL }},
6757 { &ei_ieee802154_frame_ver, { "wpan.frame_version_unknown", PI_MALFORMED, PI_ERROR,
6758 "Frame Version Unknown Cannot Dissect", EXPFILL }},
6759 #if 0
6760 { &ei_ieee802154_frame_type, { "wpan.frame_type_unknown", PI_MALFORMED, PI_ERROR,
6761 "Frame Type Unknown Cannot Dissect", EXPFILL }},
6762 #endif
6763 { &ei_ieee802154_decrypt_error, { "wpan.decrypt_error", PI_UNDECODED, PI_WARN,
6764 "Decryption error", EXPFILL }},
6765 { &ei_ieee802154_fcs, { "wpan.fcs.bad", PI_CHECKSUM, PI_WARN,
6766 "Bad FCS", EXPFILL }},
6767 { &ei_ieee802154_ack_not_found, { "wpan.ack_not_found", PI_SEQUENCE, PI_NOTE,
6768 "Ack not found", EXPFILL }},
6769 { &ei_ieee802154_ack_request_not_found, { "wpan.ack_request_not_found", PI_SEQUENCE, PI_NOTE,
6770 "Request not found", EXPFILL }},
6771 { &ei_ieee802154_seqno_suppression, { "wpan.seqno_suppression_invalid", PI_MALFORMED, PI_WARN,
6772 "Sequence Number Suppression invalid for 802.15.4-2003 and 2006", EXPFILL }},
6773 { &ei_ieee802154_6top_unsupported_type, { "wpan.6top_unsupported_type", PI_PROTOCOL, PI_WARN,
6774 "Unsupported Type of Message", EXPFILL }},
6775 { &ei_ieee802154_6top_unsupported_command, { "wpan.6top_unsupported_command", PI_PROTOCOL, PI_WARN,
6776 "Unsupported 6top command", EXPFILL }},
6777 { &ei_ieee802154_time_correction_error, { "wpan.time_correction.error", PI_PROTOCOL, PI_WARN,
6778 "Incorrect value. Reference: IEEE-802.15.4-2015. Table 7-8: Values of the Time Sync Info field for ACK with timing information", EXPFILL}},
6779 { &ei_ieee802154_6top_unsupported_return_code, { "wpan.6top_unsupported_code", PI_PROTOCOL, PI_WARN,
6780 "Unsupported 6top return code", EXPFILL }},
6781 { &ei_ieee802154_ie_unsupported_id, { "wpan.ie_unsupported_id", PI_PROTOCOL, PI_WARN,
6782 "Unsupported IE ID", EXPFILL }},
6783 { &ei_ieee802154_ie_unknown_extra_content, { "wpan.ie_unknown_extra_content", PI_PROTOCOL, PI_WARN,
6784 "Unexpected extra content for IE", EXPFILL }},
6785 { &ei_ieee802159_mpx_invalid_transfer_type, { "wpan.payload_ie.mpx.invalid_transfer_type", PI_PROTOCOL, PI_WARN,
6786 "Invalid transfer type (cf. IEEE 802.15.9 Table 19)", EXPFILL }},
6787 { &ei_ieee802159_mpx_unsupported_kmp, { "wpan.mpx.unsupported_kmp", PI_PROTOCOL, PI_WARN,
6788 "Unsupported KMP ID", EXPFILL }},
6789 { &ei_ieee802159_mpx_unknown_kmp, { "wpan.mpx.unknown_kmp", PI_PROTOCOL, PI_WARN,
6790 "Unknown KMP ID (cf. IEEE 802.15.9 Table 21)", EXPFILL }},
6791 { &ei_ieee802154_missing_payload_ie, { "wpan.payload_ie.missing", PI_MALFORMED, PI_WARN,
6792 "Payload IE indicated by Header Termination, but no Payload IE present", EXPFILL }},
6793 { &ei_ieee802154_payload_ie_in_header, { "wpan.payload_ie.in_header", PI_MALFORMED, PI_WARN,
6794 "Payload IE in header", EXPFILL }},
6795 { &ei_ieee802154_unsupported_cmd, { "wpan.cmd.unsupported_cmd", PI_PROTOCOL, PI_WARN,
6796 "Unsupported Command ID", EXPFILL }},
6797 { &ei_ieee802154_unknown_cmd, { "wpan.cmd.unknown_cmd", PI_PROTOCOL, PI_WARN,
6798 "Unknown Command Id (cf. IEEE 802.15.4-2015 Table 7-49)", EXPFILL }},
6799 { &ei_ieee802154_tap_tlv_invalid_type, { "wpan-tap.tlv.invalid_type", PI_MALFORMED, PI_WARN,
6800 "Invalid TLV type", EXPFILL }},
6801 { &ei_ieee802154_tap_tlv_invalid_length, { "wpan-tap.tlv.invalid_length", PI_MALFORMED, PI_WARN,
6802 "Invalid TLV length", EXPFILL }},
6803 { &ei_ieee802154_tap_tlv_padding_not_zeros, { "wpan-tap.tlv.padding_not_zeros", PI_MALFORMED, PI_WARN,
6804 "TLV padding not zero", EXPFILL }},
6805 { &ei_ieee802154_tap_tlv_invalid_fcs_type, { "wpan-tap.tlv.invalid_fcs_type", PI_MALFORMED, PI_ERROR,
6806 "Invalid FCS type", EXPFILL }},
6807 };
6808
6809 /* Preferences. */
6810 module_t *ieee802154_module;
6811 expert_module_t* expert_ieee802154;
6812
6813 static uat_field_t addr_uat_flds[] = {
6814 UAT_FLD_HEX(addr_uat,addr16,"Short Address",
6815 "16-bit short address in hexadecimal."),
6816 UAT_FLD_HEX(addr_uat,pan,"PAN Identifier",
6817 "16-bit PAN identifier in hexadecimal."),
6818 UAT_FLD_BUFFER(addr_uat,eui64,"EUI-64",
6819 "64-bit extended unique identifier."),
6820 UAT_END_FIELDS
6821 };
6822
6823 static uat_field_t key_uat_flds[] = {
6824 UAT_FLD_CSTRING(key_uat,pref_key,"Decryption key",
6825 "128-bit decryption key in hexadecimal format"),
6826 UAT_FLD_DEC(key_uat,key_index,"Decryption key index",
6827 "Key index in decimal format"),
6828 UAT_FLD_VS(key_uat, hash_type, "Key hash", ieee802154_key_hash_vals, "Specifies which hash scheme is used to derived the key"),
6829 UAT_END_FIELDS
6830 };
6831
6832 static const enum_val_t fcs_type_vals[] = {
6833 {"cc24xx", "TI CC24xx metadata", IEEE802154_CC24XX_METADATA},
6834 {"16", "ITU-T CRC-16", IEEE802154_FCS_16_BIT},
6835 {"32", "ITU-T CRC-32", IEEE802154_FCS_32_BIT},
6836 {NULL, NULL, -1}
6837 };
6838
6839 static build_valid_func ieee802154_da_build_value[1] = {ieee802154_da_value};
6840 static decode_as_value_t ieee802154_da_values = {ieee802154_da_prompt, 1, ieee802154_da_build_value};
6841 static decode_as_t ieee802154_da = {
6842 IEEE802154_PROTOABBREV_WPAN, IEEE802154_PROTOABBREV_WPAN_PANID,
6843 1, 0, &ieee802154_da_values, NULL, NULL,
6844 decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL
6845 };
6846
6847 /* Register the init routine. */
6848 register_init_routine(proto_init_ieee802154);
6849 register_cleanup_routine(proto_cleanup_ieee802154);
6850
6851 /* Register Protocol name and description. */
6852 proto_ieee802154 = proto_register_protocol("IEEE 802.15.4 Low-Rate Wireless PAN", "IEEE 802.15.4",
6853 IEEE802154_PROTOABBREV_WPAN);
6854 proto_ieee802154_nonask_phy = proto_register_protocol("IEEE 802.15.4 Low-Rate Wireless PAN non-ASK PHY",
6855 "IEEE 802.15.4 non-ASK PHY", "wpan-nonask-phy");
6856 proto_zboss = proto_register_protocol("ZBOSS IEEE 802.15.4 dump",
6857 "ZBOSS dump", "wpan-zboss");
6858 proto_ieee802154_tap = proto_register_protocol("IEEE 802.15.4 Low-Rate Wireless PAN TAP",
6859 "IEEE 802.15.4 TAP", "wpan-tap");
6860
6861 /* Register header fields and subtrees. */
6862 proto_register_field_array(proto_ieee802154, hf, array_length(hf));
6863 proto_register_field_array(proto_ieee802154, hf_phy, array_length(hf_phy));
6864
6865 proto_register_subtree_array(ett, array_length(ett));
6866
6867 expert_ieee802154 = expert_register_protocol(proto_ieee802154);
6868 expert_register_field_array(expert_ieee802154, ei, array_length(ei));
6869
6870 ieee802_15_4_short_address_type = address_type_dissector_register("AT_IEEE_802_15_4_SHORT", "IEEE 802.15.4 16-bit short address",
6871 ieee802_15_4_short_address_to_str, ieee802_15_4_short_address_str_len, NULL, NULL, ieee802_15_4_short_address_len, NULL, NULL);
6872
6873 /* add a user preference to set the 802.15.4 ethertype */
6874 ieee802154_module = prefs_register_protocol(proto_ieee802154,
6875 proto_reg_handoff_ieee802154);
6876 prefs_register_uint_preference(ieee802154_module, "802154_ethertype",
6877 "802.15.4 Ethertype (in hex)",
6878 "(Hexadecimal) Ethertype used to indicate IEEE 802.15.4 frame.",
6879 16, &ieee802154_ethertype);
6880 prefs_register_obsolete_preference(ieee802154_module, "802154_cc24xx");
6881 prefs_register_enum_preference(ieee802154_module, "fcs_format",
6882 "FCS format",
6883 "The FCS format in the captured payload",
6884 &ieee802154_fcs_type, fcs_type_vals, FALSE);
6885 prefs_register_bool_preference(ieee802154_module, "802154_fcs_ok",
6886 "Dissect only good FCS",
6887 "Dissect payload only if FCS is valid.",
6888 &ieee802154_fcs_ok);
6889 prefs_register_bool_preference(ieee802154_module, "802154_ack_tracking",
6890 "Enable ACK tracking",
6891 "Match frames with ACK request to ACK packets",
6892 &ieee802154_ack_tracking);
6893 prefs_register_bool_preference(ieee802154_module, "802154e_compatibility",
6894 "Assume 802.15.4e-2012 for compatibility",
6895 "Parse assuming 802.15.4e quirks for compatibility",
6896 &ieee802154e_compatibility);
6897
6898 /* Create a UAT for static address mappings. */
6899 static_addr_uat = uat_new("Static Addresses",
6900 sizeof(static_addr_t), /* record size */
6901 "802154_addresses", /* filename */
6902 TRUE, /* from_profile */
6903 &static_addrs, /* data_ptr */
6904 &num_static_addrs, /* numitems_ptr */
6905 UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */
6906 NULL, /* help */
6907 addr_uat_copy_cb, /* copy callback */
6908 addr_uat_update_cb, /* update callback */
6909 addr_uat_free_cb, /* free callback */
6910 NULL, /* post update callback */
6911 NULL, /* reset callback */
6912 addr_uat_flds); /* UAT field definitions */
6913 prefs_register_uat_preference(ieee802154_module, "static_addr",
6914 "Static Addresses",
6915 "A table of static address mappings between 16-bit short addressing and EUI-64 addresses",
6916 static_addr_uat);
6917
6918 /* Create a UAT for key management. */
6919 ieee802154_key_uat = uat_new("Keys",
6920 sizeof(ieee802154_key_t), /* record size */
6921 "ieee802154_keys", /* filename */
6922 TRUE, /* from_profile */
6923 &ieee802154_keys, /* data_ptr */
6924 &num_ieee802154_keys, /* numitems_ptr */
6925 UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */
6926 NULL, /* help */
6927 ieee802154_key_copy_cb, /* copy callback */
6928 ieee802154_key_update_cb, /* update callback */
6929 ieee802154_key_free_cb, /* free callback */
6930 ieee802154_key_post_update_cb, /* post update callback */
6931 NULL, /* reset callback */
6932 key_uat_flds); /* UAT field definitions */
6933 prefs_register_uat_preference(ieee802154_module, "ieee802154_keys",
6934 "Decryption Keys",
6935 "Decryption key configuration data",
6936 ieee802154_key_uat);
6937
6938 /* Register preferences for a decryption key */
6939 prefs_register_obsolete_preference(ieee802154_module, "802154_key");
6940
6941 prefs_register_enum_preference(ieee802154_module, "802154_sec_suite",
6942 "Security Suite (802.15.4-2003)",
6943 "Specifies the security suite to use for 802.15.4-2003 secured frames"
6944 " (only supported suites are listed). Option ignored for 802.15.4-2006"
6945 " and unsecured frames.",
6946 &ieee802154_sec_suite, ieee802154_2003_sec_suite_enums, FALSE);
6947
6948 prefs_register_bool_preference(ieee802154_module, "802154_extend_auth",
6949 "Extend authentication data (802.15.4-2003)",
6950 "Set if the manufacturer extends the authentication data with the"
6951 " security header. Option ignored for 802.15.4-2006 and unsecured frames.",
6952 &ieee802154_extend_auth);
6953
6954 /* Register the subdissector list */
6955 panid_dissector_table = register_dissector_table(IEEE802154_PROTOABBREV_WPAN_PANID, "IEEE 802.15.4 PANID", proto_ieee802154, FT_UINT16, BASE_HEX);
6956 ieee802154_heur_subdissector_list = register_heur_dissector_list(IEEE802154_PROTOABBREV_WPAN, proto_ieee802154);
6957 ieee802154_beacon_subdissector_list = register_heur_dissector_list(IEEE802154_PROTOABBREV_WPAN_BEACON, proto_ieee802154);
6958
6959 /* Register dissector tables */
6960 header_ie_dissector_table = register_dissector_table(IEEE802154_HEADER_IE_DTABLE, "IEEE 802.15.4 Header IEs", proto_ieee802154, FT_UINT8, BASE_HEX);
6961 payload_ie_dissector_table = register_dissector_table(IEEE802154_PAYLOAD_IE_DTABLE, "IEEE 802.15.4 Payload IEs", proto_ieee802154, FT_UINT8, BASE_HEX);
6962 mlme_ie_dissector_table = register_dissector_table(IEEE802154_MLME_IE_DTABLE, "IEEE 802.15.4 Nested IEs", proto_ieee802154, FT_UINT8, BASE_HEX);
6963 cmd_vendor_dissector_table = register_dissector_table(IEEE802154_CMD_VENDOR_DTABLE, "IEEE 802.15.4 Vendor Specific Commands", proto_ieee802154, FT_UINT24, BASE_HEX );
6964
6965 /* Register dissectors with Wireshark */
6966 ieee802154_handle = register_dissector(IEEE802154_PROTOABBREV_WPAN, dissect_ieee802154, proto_ieee802154);
6967 ieee802154_nofcs_handle = register_dissector("wpan_nofcs", dissect_ieee802154_nofcs, proto_ieee802154);
6968 register_dissector("wpan_cc24xx", dissect_ieee802154_cc24xx, proto_ieee802154);
6969 ieee802154_nonask_phy_handle = register_dissector("wpan-nonask-phy", dissect_ieee802154_nonask_phy, proto_ieee802154_nonask_phy);
6970 ieee802154_tap_handle = register_dissector("wpan-tap", dissect_ieee802154_tap, proto_ieee802154_tap);
6971
6972 /* Setup registration for other dissectors to provide mac key hash algorithms */
6973 mac_key_hash_handlers = wmem_tree_new(wmem_epan_scope());
6974
6975 /* Register a Decode-As handler */
6976 register_decode_as(&ieee802154_da);
6977
6978 /* Create trees for transactions */
6979 transaction_unmatched_pdus = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
6980 transaction_matched_pdus = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
6981
6982 ieee802154_tap = register_tap(IEEE802154_PROTOABBREV_WPAN);
6983
6984 register_conversation_table(proto_ieee802154, TRUE, ieee802154_conversation_packet, ieee802154_hostlist_packet);
6985 register_conversation_filter(IEEE802154_PROTOABBREV_WPAN, "IEEE 802.15.4", ieee802154_filter_valid, ieee802154_build_filter);
6986 } /* proto_register_ieee802154 */
6987
6988
6989 /**
6990 * Registers the IEEE 802.15.4 dissector with Wireshark.
6991 * Will be called every time 'apply' is pressed in the preferences menu.
6992 * as well as during Wireshark initialization
6993 */
proto_reg_handoff_ieee802154(void)6994 void proto_reg_handoff_ieee802154(void)
6995 {
6996 static gboolean prefs_initialized = FALSE;
6997 static unsigned int old_ieee802154_ethertype;
6998
6999 if (!prefs_initialized) {
7000 /* Get the dissector handles. */
7001 zigbee_ie_handle = find_dissector_add_dependency("zbee_ie", proto_ieee802154);
7002 zigbee_nwk_handle = find_dissector("zbee_nwk");
7003
7004 dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE802_15_4, ieee802154_handle);
7005 dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE802_15_4_NONASK_PHY, ieee802154_nonask_phy_handle);
7006 dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE802_15_4_NOFCS, ieee802154_nofcs_handle);
7007 dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE802_15_4_TAP, ieee802154_tap_handle);
7008 dissector_add_uint("sll.ltype", LINUX_SLL_P_IEEE802154, ieee802154_handle);
7009
7010 prefs_initialized = TRUE;
7011 } else {
7012 dissector_delete_uint("ethertype", old_ieee802154_ethertype, ieee802154_handle);
7013 }
7014
7015 old_ieee802154_ethertype = ieee802154_ethertype;
7016
7017 /* Register dissector handles. */
7018 dissector_add_uint("ethertype", ieee802154_ethertype, ieee802154_handle);
7019
7020 /* Register internal IE handlers */
7021 dissector_add_uint(IEEE802154_HEADER_IE_DTABLE, IEEE802154_HEADER_IE_TIME_CORR, create_dissector_handle(dissect_hie_time_correction, -1));
7022 dissector_add_uint(IEEE802154_HEADER_IE_DTABLE, IEEE802154_HEADER_IE_CSL, create_dissector_handle(dissect_hie_csl, -1));
7023 dissector_add_uint(IEEE802154_HEADER_IE_DTABLE, IEEE802154_HEADER_IE_GLOBAL_TIME, create_dissector_handle(dissect_hie_global_time, -1));
7024 dissector_add_uint(IEEE802154_HEADER_IE_DTABLE, IEEE802154_HEADER_IE_VENDOR_SPECIFIC, create_dissector_handle(dissect_hie_vendor_specific, -1));
7025
7026 dissector_add_uint(IEEE802154_PAYLOAD_IE_DTABLE, IEEE802154_PAYLOAD_IE_MLME, create_dissector_handle(dissect_pie_mlme, -1));
7027 dissector_add_uint(IEEE802154_PAYLOAD_IE_DTABLE, IEEE802154_PAYLOAD_IE_VENDOR, create_dissector_handle(dissect_pie_vendor, -1));
7028 dissector_add_uint(IEEE802154_PAYLOAD_IE_DTABLE, IEEE802154_PAYLOAD_IE_MPX, create_dissector_handle(dissect_mpx_ie, -1));
7029 dissector_add_uint(IEEE802154_PAYLOAD_IE_DTABLE, IEEE802154_PAYLOAD_IE_IETF, create_dissector_handle(dissect_ietf_ie, -1));
7030
7031 dissector_add_uint(IEEE802154_MLME_IE_DTABLE, IEEE802154_MLME_SUBIE_CHANNEL_HOPPING, create_dissector_handle(dissect_802154_channel_hopping, -1));
7032 dissector_add_uint(IEEE802154_MLME_IE_DTABLE, IEEE802154_MLME_SUBIE_TSCH_SYNCH, create_dissector_handle(dissect_802154_tsch_time_sync, -1));
7033 dissector_add_uint(IEEE802154_MLME_IE_DTABLE, IEEE802154_MLME_SUBIE_TSCH_SLOTFR_LINK, create_dissector_handle(dissect_802154_tsch_slotframe_link, -1));
7034 dissector_add_uint(IEEE802154_MLME_IE_DTABLE, IEEE802154_MLME_SUBIE_TSCH_TIMESLOT, create_dissector_handle(dissect_802154_tsch_timeslot, -1));
7035 dissector_add_uint(IEEE802154_MLME_IE_DTABLE, IEEE802154_MLME_SUBIE_ENHANCED_BEACON_FILTER, create_dissector_handle(dissect_802154_eb_filter, -1));
7036
7037 /* For the MPX-IE */
7038 ethertype_table = find_dissector_table("ethertype");
7039 eapol_handle = find_dissector("eapol");
7040 lowpan_handle = find_dissector("6lowpan");
7041 wisun_sec_handle = find_dissector("wisun.sec");
7042 } /* proto_reg_handoff_ieee802154 */
7043
7044 /*
7045 * Editor modelines - https://www.wireshark.org/tools/modelines.html
7046 *
7047 * Local variables:
7048 * c-basic-offset: 4
7049 * tab-width: 8
7050 * indent-tabs-mode: nil
7051 * End:
7052 *
7053 * vi: set shiftwidth=4 tabstop=8 expandtab:
7054 * :indentSize=4:tabSize=8:noTabs=true:
7055 */
7056