PageRenderTime 66ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/epan/dissectors/packet-ieee802154.c

https://github.com/labx-technologies-llc/wireshark
C | 2806 lines | 1635 code | 326 blank | 845 comment | 300 complexity | d478e8a8a02678e6e8f8e4e714a3f0ec MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause
  1. /* packet-ieee802154.c
  2. *
  3. * $Id$
  4. *
  5. * Auxiliary Security Header support and
  6. * option to force TI CC24xx FCS format
  7. * By Jean-Francois Wauthy <jfw@info.fundp.ac.be>
  8. * Copyright 2009 The University of Namur, Belgium
  9. *
  10. * IEEE 802.15.4 Dissectors for Wireshark
  11. * By Owen Kirby <osk@exegin.com>
  12. * Copyright 2007 Exegin Technologies Limited
  13. *
  14. * Wireshark - Network traffic analyzer
  15. * By Gerald Combs <gerald@wireshark.org>
  16. * Copyright 1998 Gerald Combs
  17. *
  18. * This program is free software; you can redistribute it and/or
  19. * modify it under the terms of the GNU General Public License
  20. * as published by the Free Software Foundation; either version 2
  21. * of the License, or (at your option) any later version.
  22. *
  23. * This program is distributed in the hope that it will be useful,
  24. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  25. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  26. * GNU General Public License for more details.
  27. *
  28. * You should have received a copy of the GNU General Public License
  29. * along with this program; if not, write to the Free Software
  30. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  31. *------------------------------------------------------------
  32. *
  33. * In IEEE 802.15.4 packets, all fields are little endian. And
  34. * Each byte is transmitted least significant bit first (reflected
  35. * bit ordering).
  36. *------------------------------------------------------------
  37. *
  38. * IEEE 802.15.4 Packets have the following format:
  39. * | FCF |Seq No| Addressing | Data | FCS |
  40. * |2 bytes|1 byte|0 to 20 bytes|Length-(Overhead) bytes|2 Bytes|
  41. *------------------------------------------------------------
  42. *
  43. * CRC16 is calculated using the x^16 + x^12 + x^5 + 1 polynomial
  44. * as specified by ITU-T, and is calculated over the IEEE 802.15.4
  45. * packet (excluding the FCS) as transmitted over the air. Note,
  46. * that because the least significan bits are transmitted first, this
  47. * will require reversing the bit-order in each byte. Also, unlike
  48. * most CRC algorithms, IEEE 802.15.4 uses an initial and final value
  49. * of 0x0000, instead of 0xffff (which is used by the CCITT).
  50. *------------------------------------------------------------
  51. *
  52. * This dissector supports both link-layer IEEE 802.15.4 captures
  53. * and IEEE 802.15.4 packets encapsulated within other layers.
  54. * Additionally, support has been provided for various formats
  55. * of the frame check sequence:
  56. * - IEEE 802.15.4 compliant FCS.
  57. * - ChipCon/Texas Instruments CC24xx style FCS.
  58. *------------------------------------------------------------
  59. */
  60. /* Include files */
  61. #include "config.h"
  62. #include <string.h>
  63. #include <sys/stat.h>
  64. #include <glib.h>
  65. #include <epan/wmem/wmem.h>
  66. #include <epan/packet.h>
  67. #include <epan/crc16-tvb.h>
  68. #include <epan/expert.h>
  69. #include <epan/addr_resolv.h>
  70. #include <epan/prefs.h>
  71. #include <epan/uat.h>
  72. #include <epan/strutil.h>
  73. #include <epan/show_exception.h>
  74. /* Use libgcrypt for cipher libraries. */
  75. #ifdef HAVE_LIBGCRYPT
  76. #include <wsutil/wsgcrypt.h>
  77. #endif /* HAVE_LIBGCRYPT */
  78. #include "packet-ieee802154.h"
  79. #include "packet-sll.h"
  80. /* Dissection Options for dissect_ieee802154_common */
  81. #define DISSECT_IEEE802154_OPTION_CC24xx 0x00000001 /* FCS field contains a TI CC24xx style FCS. */
  82. #define DISSECT_IEEE802154_OPTION_LINUX 0x00000002 /* Addressing fields are padded DLT_IEEE802_15_4_LINUX, not implemented. */
  83. /* ethertype for 802.15.4 tag - encapsulating an Ethernet packet */
  84. static unsigned int ieee802154_ethertype = 0x809A;
  85. /* boolean value set if the FCS field is using the TI CC24xx format */
  86. static gboolean ieee802154_cc24xx = FALSE;
  87. /* boolean value set if the FCS must be ok before payload is dissected */
  88. static gboolean ieee802154_fcs_ok = TRUE;
  89. /* User string with the decryption key. */
  90. static const gchar *ieee802154_key_str = NULL;
  91. static gboolean ieee802154_key_valid;
  92. static guint8 ieee802154_key[IEEE802154_CIPHER_SIZE];
  93. static const char *ieee802154_user = "User";
  94. /*-------------------------------------
  95. * Address Hash Tables
  96. *-------------------------------------
  97. */
  98. static ieee802154_map_tab_t ieee802154_map = { NULL, NULL };
  99. /*-------------------------------------
  100. * Static Address Mapping UAT
  101. *-------------------------------------
  102. */
  103. /* UAT entry structure. */
  104. typedef struct {
  105. guchar *eui64;
  106. guint eui64_len;
  107. guint addr16;
  108. guint pan;
  109. } static_addr_t;
  110. /* UAT variables */
  111. static uat_t *static_addr_uat = NULL;
  112. static static_addr_t *static_addrs = NULL;
  113. static guint num_static_addrs = 0;
  114. /* Sanity-checks a UAT record. */
  115. static void
  116. addr_uat_update_cb(void *r, const char **err)
  117. {
  118. static_addr_t *map = (static_addr_t *)r;
  119. /* Ensure a valid short address */
  120. if (map->addr16 >= IEEE802154_NO_ADDR16) {
  121. *err = "Invalid short address";
  122. }
  123. /* Ensure a valid PAN identifier. */
  124. if (map->pan >= IEEE802154_BCAST_PAN) {
  125. *err = "Invalid PAN identifier";
  126. }
  127. /* Ensure a valid EUI-64 length */
  128. if (map->eui64_len != sizeof(guint64)) {
  129. *err = "Invalid EUI-64 length";
  130. }
  131. } /* ieee802154_addr_uat_update_cb */
  132. /* Field callbacks. */
  133. UAT_HEX_CB_DEF(addr_uat, addr16, static_addr_t)
  134. UAT_HEX_CB_DEF(addr_uat, pan, static_addr_t)
  135. UAT_BUFFER_CB_DEF(addr_uat, eui64, static_addr_t, eui64, eui64_len)
  136. /*-------------------------------------
  137. * Dissector Function Prototypes
  138. *-------------------------------------
  139. */
  140. /* Register Functions. Loads the dissector into Wireshark. */
  141. void proto_reg_handoff_ieee802154 (void);
  142. /* Dissection Routines. */
  143. static void dissect_ieee802154_nonask_phy (tvbuff_t *, packet_info *, proto_tree *);
  144. static void dissect_ieee802154 (tvbuff_t *, packet_info *, proto_tree *);
  145. static void dissect_ieee802154_nofcs (tvbuff_t *, packet_info *, proto_tree *);
  146. static void dissect_ieee802154_cc24xx (tvbuff_t *, packet_info *, proto_tree *);
  147. /*static void dissect_ieee802154_linux (tvbuff_t *, packet_info *, proto_tree *); TODO: Implement Me. */
  148. static void dissect_ieee802154_common (tvbuff_t *, packet_info *, proto_tree *, guint);
  149. /* Sub-dissector helpers. */
  150. static void dissect_ieee802154_fcf (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *, guint *);
  151. static void dissect_ieee802154_superframe (tvbuff_t *, packet_info *, proto_tree *, guint *);
  152. static void dissect_ieee802154_gtsinfo (tvbuff_t *, packet_info *, proto_tree *, guint *);
  153. static void dissect_ieee802154_pendaddr (tvbuff_t *, packet_info *, proto_tree *, guint *);
  154. static void dissect_ieee802154_assoc_req (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
  155. static void dissect_ieee802154_assoc_rsp (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
  156. static void dissect_ieee802154_disassoc (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
  157. static void dissect_ieee802154_realign (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
  158. static void dissect_ieee802154_gtsreq (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
  159. /* Decryption helpers. */
  160. typedef enum {
  161. DECRYPT_PACKET_SUCCEEDED,
  162. DECRYPT_NOT_ENCRYPTED,
  163. DECRYPT_VERSION_UNSUPPORTED,
  164. DECRYPT_PACKET_TOO_SMALL,
  165. DECRYPT_PACKET_NO_EXT_SRC_ADDR,
  166. DECRYPT_PACKET_NO_KEY,
  167. DECRYPT_PACKET_DECRYPT_FAILED,
  168. DECRYPT_PACKET_MIC_CHECK_FAILED
  169. } ws_decrypt_status;
  170. static tvbuff_t * dissect_ieee802154_decrypt(tvbuff_t *, guint, packet_info *, ieee802154_packet *,
  171. ws_decrypt_status *);
  172. static void ccm_init_block (gchar *, gboolean, gint, guint64, ieee802154_packet *, gint);
  173. static gboolean ccm_ctr_encrypt (const gchar *, const gchar *, gchar *, gchar *, gint);
  174. static gboolean ccm_cbc_mac (const gchar *, const gchar *, const gchar *, gint, const gchar *, gint, gchar *);
  175. /* Initialize Protocol and Registered fields */
  176. static int proto_ieee802154_nonask_phy = -1;
  177. static int hf_ieee802154_nonask_phy_preamble = -1;
  178. static int hf_ieee802154_nonask_phy_sfd = -1;
  179. static int hf_ieee802154_nonask_phy_length = -1;
  180. static int proto_ieee802154 = -1;
  181. static int hf_ieee802154_frame_length = -1;
  182. static int hf_ieee802154_frame_type = -1;
  183. static int hf_ieee802154_security = -1;
  184. static int hf_ieee802154_pending = -1;
  185. static int hf_ieee802154_ack_request = -1;
  186. static int hf_ieee802154_intra_pan = -1;
  187. static int hf_ieee802154_seqno = -1;
  188. static int hf_ieee802154_src_addr_mode = -1;
  189. static int hf_ieee802154_dst_addr_mode = -1;
  190. static int hf_ieee802154_version = -1;
  191. static int hf_ieee802154_dst_panID = -1;
  192. static int hf_ieee802154_dst16 = -1;
  193. static int hf_ieee802154_dst64 = -1;
  194. static int hf_ieee802154_src_panID = -1;
  195. static int hf_ieee802154_src16 = -1;
  196. static int hf_ieee802154_src64 = -1;
  197. static int hf_ieee802154_src64_origin = -1;
  198. static int hf_ieee802154_fcs = -1;
  199. static int hf_ieee802154_rssi = -1;
  200. static int hf_ieee802154_fcs_ok = -1;
  201. static int hf_ieee802154_correlation = -1;
  202. /* Registered fields for Command Packets */
  203. static int hf_ieee802154_cmd_id = -1;
  204. static int hf_ieee802154_cinfo_alt_coord = -1;
  205. static int hf_ieee802154_cinfo_device_type = -1;
  206. static int hf_ieee802154_cinfo_power_src = -1;
  207. static int hf_ieee802154_cinfo_idle_rx = -1;
  208. static int hf_ieee802154_cinfo_sec_capable = -1;
  209. static int hf_ieee802154_cinfo_alloc_addr = -1;
  210. static int hf_ieee802154_assoc_addr = -1;
  211. static int hf_ieee802154_assoc_status = -1;
  212. static int hf_ieee802154_disassoc_reason = -1;
  213. static int hf_ieee802154_realign_pan = -1;
  214. static int hf_ieee802154_realign_caddr = -1;
  215. static int hf_ieee802154_realign_channel = -1;
  216. static int hf_ieee802154_realign_addr = -1;
  217. static int hf_ieee802154_realign_channel_page = -1;
  218. static int hf_ieee802154_gtsreq_len = -1;
  219. static int hf_ieee802154_gtsreq_dir = -1;
  220. static int hf_ieee802154_gtsreq_type = -1;
  221. /* Registered fields for Beacon Packets */
  222. static int hf_ieee802154_beacon_order = -1;
  223. static int hf_ieee802154_superframe_order = -1;
  224. static int hf_ieee802154_cap = -1;
  225. static int hf_ieee802154_superframe_battery_ext = -1;
  226. static int hf_ieee802154_superframe_coord = -1;
  227. static int hf_ieee802154_assoc_permit = -1;
  228. static int hf_ieee802154_gts_count = -1;
  229. static int hf_ieee802154_gts_permit = -1;
  230. static int hf_ieee802154_gts_direction = -1;
  231. static int hf_ieee802154_pending16 = -1;
  232. static int hf_ieee802154_pending64 = -1;
  233. /* Registered fields for Auxiliary Security Header */
  234. static int hf_ieee802154_security_level = -1;
  235. static int hf_ieee802154_key_id_mode = -1;
  236. static int hf_ieee802154_aux_sec_reserved = -1;
  237. static int hf_ieee802154_aux_sec_frame_counter = -1;
  238. static int hf_ieee802154_aux_sec_key_source = -1;
  239. static int hf_ieee802154_aux_sec_key_index = -1;
  240. /* 802.15.4-2003 security */
  241. static int hf_ieee802154_sec_frame_counter = -1;
  242. static int hf_ieee802154_sec_key_sequence_counter = -1;
  243. /* Initialize Subtree Pointers */
  244. static gint ett_ieee802154_nonask_phy = -1;
  245. static gint ett_ieee802154_nonask_phy_phr = -1;
  246. static gint ett_ieee802154 = -1;
  247. static gint ett_ieee802154_fcf = -1;
  248. static gint ett_ieee802154_auxiliary_security = -1;
  249. static gint ett_ieee802154_aux_sec_control = -1;
  250. static gint ett_ieee802154_aux_sec_key_id = -1;
  251. static gint ett_ieee802154_fcs = -1;
  252. static gint ett_ieee802154_cmd = -1;
  253. static gint ett_ieee802154_superframe = -1;
  254. static gint ett_ieee802154_gts = -1;
  255. static gint ett_ieee802154_gts_direction = -1;
  256. static gint ett_ieee802154_gts_descriptors = -1;
  257. static gint ett_ieee802154_pendaddr = -1;
  258. /* Dissector handles */
  259. static dissector_handle_t data_handle;
  260. static heur_dissector_list_t ieee802154_heur_subdissector_list;
  261. /* Name Strings */
  262. static const value_string ieee802154_frame_types[] = {
  263. { IEEE802154_FCF_BEACON, "Beacon" },
  264. { IEEE802154_FCF_DATA, "Data" },
  265. { IEEE802154_FCF_ACK, "Ack" },
  266. { IEEE802154_FCF_CMD, "Command" },
  267. { 0, NULL }
  268. };
  269. static const value_string ieee802154_addr_modes[] = {
  270. { IEEE802154_FCF_ADDR_NONE, "None" },
  271. { IEEE802154_FCF_ADDR_SHORT,"Short/16-bit" },
  272. { IEEE802154_FCF_ADDR_EXT, "Long/64-bit" },
  273. { 0, NULL }
  274. };
  275. static const value_string ieee802154_cmd_names[] = {
  276. { IEEE802154_CMD_ASRQ, "Association Request" },
  277. { IEEE802154_CMD_ASRSP, "Association Response" },
  278. { IEEE802154_CMD_DISAS, "Disassociation Notification" },
  279. { IEEE802154_CMD_DATA_RQ, "Data Request" },
  280. { IEEE802154_CMD_PANID_ERR, "PAN ID Conflict" },
  281. { IEEE802154_CMD_ORPH_NOTIF,"Orphan Notification" },
  282. { IEEE802154_CMD_BCN_RQ, "Beacon Request" },
  283. { IEEE802154_CMD_COORD_REAL,"Coordinator Realignment" },
  284. { IEEE802154_CMD_GTS_REQ, "GTS Request" },
  285. { 0, NULL }
  286. };
  287. static const value_string ieee802154_sec_level_names[] = {
  288. { SECURITY_LEVEL_NONE, "No Security" },
  289. { SECURITY_LEVEL_MIC_32, "32-bit Message Integrity Code" },
  290. { SECURITY_LEVEL_MIC_64, "64-bit Message Integrity Code" },
  291. { SECURITY_LEVEL_MIC_128, "128-bit Message Integrity Code" },
  292. { SECURITY_LEVEL_ENC, "Encryption" },
  293. { SECURITY_LEVEL_ENC_MIC_32, "Encryption with 32-bit Message Integrity Code" },
  294. { SECURITY_LEVEL_ENC_MIC_64, "Encryption with 64-bit Message Integrity Code" },
  295. { SECURITY_LEVEL_ENC_MIC_128, "Encryption with 128-bit Message Integrity Code" },
  296. { 0, NULL }
  297. };
  298. static const value_string ieee802154_key_id_mode_names[] = {
  299. { KEY_ID_MODE_IMPLICIT, "Implicit Key" },
  300. { KEY_ID_MODE_KEY_INDEX, "Indexed Key using the Default Key Source" },
  301. { KEY_ID_MODE_KEY_EXPLICIT_4, "Explicit Key with 4-octet Key Source" },
  302. { KEY_ID_MODE_KEY_EXPLICIT_8, "Explicit Key with 8-octet Key Source" },
  303. { 0, NULL }
  304. };
  305. static const true_false_string ieee802154_gts_direction_tfs = {
  306. "Receive Only",
  307. "Transmit Only"
  308. };
  309. /* The 802.15.4-2003 security suites for the security preferences (only AES-CCM suites are supported). */
  310. /* NOTE: The equivalent 2006 security level identifer enumerations are used to simplify 2003 & 2006 integration! */
  311. static const enum_val_t ieee802154_2003_sec_suite_enums[] = {
  312. { "AES-CCM-128", "AES-128 Encryption, 128-bit Integrity Protection", SECURITY_LEVEL_ENC_MIC_128 },
  313. { "AES-CCM-64", "AES-128 Encryption, 64-bit Integrity Protection", SECURITY_LEVEL_ENC_MIC_64 },
  314. { "AES-CCM-32", "AES-128 Encryption, 32-bit Integrity Protection", SECURITY_LEVEL_ENC_MIC_32 },
  315. { NULL, NULL, 0 }
  316. };
  317. /* Preferences for 2003 security */
  318. static gint ieee802154_sec_suite = SECURITY_LEVEL_ENC_MIC_64;
  319. static gboolean ieee802154_extend_auth = TRUE;
  320. /* Macro to check addressing, and throw a warning flag if incorrect. */
  321. #define IEEE802154_CMD_ADDR_CHECK(_pinfo_, _item_, _cmdid_, _x_) \
  322. if (!(_x_)) \
  323. expert_add_info_format(_pinfo_, _item_, PI_MALFORMED, PI_WARN, \
  324. "Invalid Addressing for %s", \
  325. val_to_str_const(_cmdid_, ieee802154_cmd_names, "Unknown Command"))
  326. /* CRC definitions. IEEE 802.15.4 CRCs vary from CCITT by using an initial value of
  327. * 0x0000, and no XOR out. IEEE802154_CRC_XOR is defined as 0xFFFF in order to un-XOR
  328. * the output from the CCITT CRC routines in Wireshark.
  329. */
  330. #define IEEE802154_CRC_SEED 0x0000
  331. #define IEEE802154_CRC_XOROUT 0xFFFF
  332. #define ieee802154_crc_tvb(tvb, offset) (crc16_ccitt_tvb_seed(tvb, offset, IEEE802154_CRC_SEED) ^ IEEE802154_CRC_XOROUT)
  333. /*FUNCTION:------------------------------------------------------
  334. * NAME
  335. * dissect_ieee802154_fcf
  336. * DESCRIPTION
  337. * Dissector helper, parses and displays the frame control
  338. * field.
  339. *
  340. * PARAMETERS
  341. * ieee802154_packet *packet - Packet info structure.
  342. * tvbuff_t *tvb - pointer to buffer containing raw packet.
  343. * packet_info *pinfo - pointer to packet information fields
  344. * proto_tree *tree - pointer to data tree wireshark uses to display packet.
  345. * ieee802154_packet *packet - IEEE 802.15.4 packet information.
  346. * guint offset - offset into the tvb to find the FCF.
  347. * RETURNS
  348. * void
  349. *---------------------------------------------------------------
  350. */
  351. static void
  352. dissect_ieee802154_fcf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet, guint *offset)
  353. {
  354. guint16 fcf;
  355. proto_tree *field_tree;
  356. proto_item *ti;
  357. /* Get the FCF field. */
  358. fcf = tvb_get_letohs(tvb, *offset);
  359. /* Parse FCF Flags. */
  360. packet->frame_type = fcf & IEEE802154_FCF_TYPE_MASK;
  361. packet->security_enable = fcf & IEEE802154_FCF_SEC_EN;
  362. packet->frame_pending = fcf & IEEE802154_FCF_FRAME_PND;
  363. packet->ack_request = fcf & IEEE802154_FCF_ACK_REQ;
  364. packet->intra_pan = fcf & IEEE802154_FCF_INTRA_PAN;
  365. packet->version = (fcf & IEEE802154_FCF_VERSION) >> 12;
  366. packet->dst_addr_mode = (fcf & IEEE802154_FCF_DADDR_MASK) >> 10;
  367. packet->src_addr_mode = (fcf & IEEE802154_FCF_SADDR_MASK) >> 14;
  368. /* Display the frame type. */
  369. proto_item_append_text(tree, " %s", val_to_str_const(packet->frame_type, ieee802154_frame_types, "Reserved"));
  370. col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet->frame_type, ieee802154_frame_types, "Reserved"));
  371. /* Add the FCF to the protocol tree. */
  372. if (tree) {
  373. /* Create the FCF subtree. */
  374. ti = proto_tree_add_text(tree, tvb, *offset, 2, "Frame Control Field: %s (0x%04x)",
  375. val_to_str_const(packet->frame_type, ieee802154_frame_types, "Unknown"), fcf);
  376. field_tree = proto_item_add_subtree(ti, ett_ieee802154_fcf);
  377. /* FCF Fields. */
  378. proto_tree_add_uint(field_tree, hf_ieee802154_frame_type, tvb, *offset, 1, fcf & IEEE802154_FCF_TYPE_MASK);
  379. proto_tree_add_boolean(field_tree, hf_ieee802154_security, tvb, *offset, 1, fcf & IEEE802154_FCF_SEC_EN);
  380. proto_tree_add_boolean(field_tree, hf_ieee802154_pending, tvb, *offset, 1, fcf & IEEE802154_FCF_FRAME_PND);
  381. proto_tree_add_boolean(field_tree, hf_ieee802154_ack_request, tvb, *offset, 1, fcf & IEEE802154_FCF_ACK_REQ);
  382. proto_tree_add_boolean(field_tree, hf_ieee802154_intra_pan, tvb, *offset, 1, fcf & IEEE802154_FCF_INTRA_PAN);
  383. proto_tree_add_uint(field_tree, hf_ieee802154_dst_addr_mode, tvb, (*offset)+1, 1, fcf & IEEE802154_FCF_DADDR_MASK);
  384. proto_tree_add_uint(field_tree, hf_ieee802154_version, tvb, (*offset)+1, 1, fcf & IEEE802154_FCF_VERSION);
  385. proto_tree_add_uint(field_tree, hf_ieee802154_src_addr_mode, tvb, (*offset)+1, 1, fcf & IEEE802154_FCF_SADDR_MASK);
  386. }
  387. *offset += 2;
  388. } /* dissect_ieee802154_fcf */
  389. /*FUNCTION:------------------------------------------------------
  390. * NAME
  391. * dissect_ieee802154_nonask_phy
  392. * DESCRIPTION
  393. * Dissector for IEEE 802.15.4 non-ASK PHY packet with an FCS containing
  394. * a 16-bit CRC value.
  395. *
  396. * PARAMETERS
  397. * tvbuff_t *tvb - pointer to buffer containing raw packet.
  398. * packet_info *pinfo - pointer to packet information fields
  399. * proto_tree *tree - pointer to data tree wireshark uses to display packet.
  400. * RETURNS
  401. * void
  402. *---------------------------------------------------------------
  403. */
  404. static void
  405. dissect_ieee802154_nonask_phy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
  406. {
  407. proto_tree *ieee802154_tree = NULL;
  408. proto_item *proto_root = NULL;
  409. guint offset = 0;
  410. guint32 preamble;
  411. guint8 sfd,phr;
  412. tvbuff_t* mac;
  413. /* Create the protocol tree. */
  414. if (tree) {
  415. proto_root = proto_tree_add_protocol_format(tree, proto_ieee802154_nonask_phy, tvb, 0, tvb_length(tvb), "IEEE 802.15.4 non-ASK PHY");
  416. ieee802154_tree = proto_item_add_subtree(proto_root, ett_ieee802154_nonask_phy);
  417. }
  418. /* Add the protocol name. */
  419. col_set_str(pinfo->cinfo, COL_PROTOCOL, "IEEE 802.15.4 non-ASK PHY");
  420. /* Add the packet length. */
  421. col_clear(pinfo->cinfo, COL_PACKET_LENGTH);
  422. col_add_fstr(pinfo->cinfo, COL_PACKET_LENGTH, "%i", tvb_length(tvb));
  423. preamble=tvb_get_letohl(tvb,offset);
  424. sfd=tvb_get_guint8(tvb,offset+4);
  425. phr=tvb_get_guint8(tvb,offset+4+1);
  426. if(tree) {
  427. proto_tree *phr_tree;
  428. proto_item *pi;
  429. guint loffset=offset;
  430. proto_tree_add_uint(ieee802154_tree, hf_ieee802154_nonask_phy_preamble, tvb, loffset, 4, preamble);
  431. loffset+=4;
  432. proto_tree_add_uint(ieee802154_tree, hf_ieee802154_nonask_phy_sfd, tvb, loffset, 1, sfd);
  433. loffset+=1;
  434. pi = proto_tree_add_text(ieee802154_tree, tvb, loffset, 1, "PHR: 0x%02x", phr);
  435. phr_tree = proto_item_add_subtree(pi, ett_ieee802154_nonask_phy_phr);
  436. proto_tree_add_uint(phr_tree, hf_ieee802154_nonask_phy_length, tvb, loffset, 1, phr);
  437. }
  438. offset+=4+2*1;
  439. mac=tvb_new_subset(tvb,offset,-1, phr & IEEE802154_PHY_LENGTH_MASK);
  440. /* Call the common dissector. */
  441. dissect_ieee802154(mac, pinfo, ieee802154_tree);
  442. } /* dissect_ieee802154_nonask_phy */
  443. /*FUNCTION:------------------------------------------------------
  444. * NAME
  445. * dissect_ieee802154
  446. * DESCRIPTION
  447. * Dissector for IEEE 802.15.4 packet with an FCS containing
  448. * a 16-bit CRC value.
  449. *
  450. * PARAMETERS
  451. * tvbuff_t *tvb - pointer to buffer containing raw packet.
  452. * packet_info *pinfo - pointer to packet information fields
  453. * proto_tree *tree - pointer to data tree wireshark uses to display packet.
  454. * RETURNS
  455. * void
  456. *---------------------------------------------------------------
  457. */
  458. static void
  459. dissect_ieee802154(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
  460. {
  461. /* Call the common dissector. */
  462. dissect_ieee802154_common(tvb, pinfo, tree, (ieee802154_cc24xx ? DISSECT_IEEE802154_OPTION_CC24xx : 0));
  463. } /* dissect_ieee802154 */
  464. /*FUNCTION:------------------------------------------------------
  465. * NAME
  466. * dissect_ieee802154_nofcs
  467. * DESCRIPTION
  468. * Dissector for IEEE 802.15.4 packet with no FCS present.
  469. *
  470. * PARAMETERS
  471. * tvbuff_t *tvb - pointer to buffer containing raw packet.
  472. * packet_info *pinfo - pointer to packet information fields
  473. * proto_tree *tree - pointer to data tree wireshark uses to display packet.
  474. * RETURNS
  475. * void
  476. *---------------------------------------------------------------
  477. */
  478. static void
  479. dissect_ieee802154_nofcs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
  480. {
  481. tvbuff_t *new_tvb;
  482. /* If there is no FCS present in the reported packet, then the length of
  483. * the true IEEE 802.15.4 packet is actually 2 bytes longer. Re-create
  484. * the buffer with an extended reported length so that the packet will
  485. * be handled as though the FCS were truncated.
  486. *
  487. * Note, we can't just call tvb_set_reported_length(), because it includes
  488. * checks to ensure that the new reported length is not longer than the old
  489. * reported length (why?), and will throw an exception.
  490. */
  491. new_tvb = tvb_new_subset(tvb, 0, -1, tvb_reported_length(tvb)+IEEE802154_FCS_LEN);
  492. /* Call the common dissector. */
  493. dissect_ieee802154_common(new_tvb, pinfo, tree, 0);
  494. } /* dissect_ieee802154_nofcs */
  495. /*FUNCTION:------------------------------------------------------
  496. * NAME
  497. * dissect_ieee802154_cc24xx
  498. * DESCRIPTION
  499. * Dissector for IEEE 802.15.4 packet with a ChipCon/Texas
  500. * Instruments compatible FCS. This is typically called by
  501. * layers encapsulating an IEEE 802.15.4 packet.
  502. *
  503. * PARAMETERS
  504. * tvbuff_t *tvb - pointer to buffer containing raw packet.
  505. * packet_info *pinfo - pointer to packet information fields
  506. * proto_tree *tree - pointer to data tree wireshark uses to display packet.
  507. * RETURNS
  508. * void
  509. *---------------------------------------------------------------
  510. */
  511. static void
  512. dissect_ieee802154_cc24xx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
  513. {
  514. /* Call the common dissector. */
  515. dissect_ieee802154_common(tvb, pinfo, tree, DISSECT_IEEE802154_OPTION_CC24xx);
  516. } /* dissect_ieee802154_cc24xx */
  517. /*FUNCTION:------------------------------------------------------
  518. * NAME
  519. * dissect_ieee802154_common
  520. * DESCRIPTION
  521. * IEEE 802.15.4 packet dissection routine for Wireshark.
  522. * This function extracts all the information first before displaying.
  523. * If payload exists, that portion will be passed into another dissector
  524. * for further processing.
  525. *
  526. * This is called after the individual dissect_ieee802154* functions
  527. * have been called to determine what sort of FCS is present.
  528. * The dissect_ieee802154* functions will set the parameters
  529. * in the ieee802154_packet structure, and pass it to this one
  530. * through the pinfo->private_data pointer.
  531. *
  532. * PARAMETERS
  533. * tvbuff_t *tvb - pointer to buffer containing raw packet.
  534. * packet_info *pinfo - pointer to packet information fields
  535. * proto_tree *tree - pointer to data tree wireshark uses to display packet.
  536. * guint options - bitwise or of dissector options (see DISSECT_IEEE802154_OPTION_xxx).
  537. * RETURNS
  538. * void
  539. *---------------------------------------------------------------
  540. */
  541. static void
  542. dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint options)
  543. {
  544. tvbuff_t *volatile payload_tvb;
  545. proto_tree *volatile ieee802154_tree = NULL;
  546. proto_item *volatile proto_root = NULL;
  547. proto_item *hidden_item;
  548. proto_item *ti;
  549. void *pd_save;
  550. guint offset = 0;
  551. volatile gboolean fcs_ok = TRUE;
  552. const char *saved_proto;
  553. ws_decrypt_status status;
  554. ieee802154_packet *packet = wmem_new(wmem_packet_scope(), ieee802154_packet);
  555. ieee802154_short_addr addr16;
  556. ieee802154_hints_t *ieee_hints;
  557. /* Link our packet info structure into the private data field for the
  558. * Network-Layer heuristic subdissectors. */
  559. pd_save = pinfo->private_data;
  560. pinfo->private_data = packet;
  561. packet->short_table = ieee802154_map.short_table;
  562. /* Allocate frame data with hints for upper layers */
  563. if(!pinfo->fd->flags.visited){
  564. ieee_hints = se_new0(ieee802154_hints_t);
  565. p_add_proto_data(pinfo->fd, proto_ieee802154, 0, ieee_hints);
  566. } else {
  567. ieee_hints = (ieee802154_hints_t *)p_get_proto_data(pinfo->fd, proto_ieee802154, 0);
  568. }
  569. /* Create the protocol tree. */
  570. if (tree) {
  571. proto_root = proto_tree_add_protocol_format(tree, proto_ieee802154, tvb, 0, tvb_length(tvb), "IEEE 802.15.4");
  572. ieee802154_tree = proto_item_add_subtree(proto_root, ett_ieee802154);
  573. }
  574. /* Add the protocol name. */
  575. col_set_str(pinfo->cinfo, COL_PROTOCOL, "IEEE 802.15.4");
  576. /* Add the packet length. */
  577. col_clear(pinfo->cinfo, COL_PACKET_LENGTH);
  578. col_add_fstr(pinfo->cinfo, COL_PACKET_LENGTH, "%i", tvb_length(tvb));
  579. /* Add the packet length to the filter field */
  580. hidden_item = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_frame_length, NULL, 0, 0, tvb_reported_length(tvb));
  581. PROTO_ITEM_SET_HIDDEN(hidden_item);
  582. /*=====================================================
  583. * FRAME CONTROL FIELD
  584. *=====================================================
  585. */
  586. dissect_ieee802154_fcf(tvb, pinfo, ieee802154_tree, packet, &offset);
  587. /*=====================================================
  588. * SEQUENCE NUMBER
  589. *=====================================================
  590. */
  591. packet->seqno = tvb_get_guint8(tvb, offset);
  592. if (tree) {
  593. proto_tree_add_uint(ieee802154_tree, hf_ieee802154_seqno, tvb, offset, 1, packet->seqno);
  594. /* For Ack packets display this in the root. */
  595. if (packet->frame_type == IEEE802154_FCF_ACK) {
  596. proto_item_append_text(proto_root, ", Sequence Number: %u", packet->seqno);
  597. }
  598. }
  599. offset += 1;
  600. /*=====================================================
  601. * ADDRESSING FIELDS
  602. *=====================================================
  603. */
  604. /* Clear out the addressing strings. */
  605. SET_ADDRESS(&pinfo->dst, AT_NONE, 0, NULL);
  606. SET_ADDRESS(&pinfo->src, AT_NONE, 0, NULL);
  607. SET_ADDRESS(&pinfo->dl_dst, AT_NONE, 0, NULL);
  608. SET_ADDRESS(&pinfo->dl_src, AT_NONE, 0, NULL);
  609. SET_ADDRESS(&pinfo->net_dst, AT_NONE, 0, NULL);
  610. SET_ADDRESS(&pinfo->net_src, AT_NONE, 0, NULL);
  611. /* Get and display the destination PAN, if present. */
  612. if ( (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) ||
  613. (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) ) {
  614. packet->dst_pan = tvb_get_letohs(tvb, offset);
  615. if (tree) {
  616. proto_tree_add_uint(ieee802154_tree, hf_ieee802154_dst_panID, tvb, offset, 2, packet->dst_pan);
  617. }
  618. offset += 2;
  619. }
  620. /* Get destination address. */
  621. if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
  622. char dst_addr[32];
  623. /* Get the address. */
  624. packet->dst16 = tvb_get_letohs(tvb, offset);
  625. /* Display the destination address. */
  626. if ( packet->dst16 == IEEE802154_BCAST_ADDR ) {
  627. g_snprintf(dst_addr, 32, "Broadcast");
  628. }
  629. else {
  630. g_snprintf(dst_addr, 32, "0x%04x", packet->dst16);
  631. }
  632. /* Provide address hints to higher layers that need it. */
  633. if (ieee_hints) {
  634. ieee_hints->dst16 = packet->dst16;
  635. }
  636. TVB_SET_ADDRESS(&pinfo->dl_dst, AT_IEEE_802_15_4_SHORT, tvb, offset, 2);
  637. TVB_SET_ADDRESS(&pinfo->dst, AT_IEEE_802_15_4_SHORT, tvb, offset, 2);
  638. if (tree) {
  639. proto_tree_add_uint(ieee802154_tree, hf_ieee802154_dst16, tvb, offset, 2, packet->dst16);
  640. proto_item_append_text(proto_root, ", Dst: %s", dst_addr);
  641. }
  642. col_append_fstr(pinfo->cinfo, COL_INFO, ", Dst: %s", dst_addr);
  643. offset += 2;
  644. }
  645. else if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) {
  646. static guint64 addr; /* has to be static due to SET_ADDRESS */
  647. /* Get the address */
  648. packet->dst64 = tvb_get_letoh64(tvb, offset);
  649. /* Copy and convert the address to network byte order. */
  650. addr = pntoh64(&(packet->dst64));
  651. /* Display the destination address. */
  652. /* XXX - OUI resolution doesn't happen when displaying resolved
  653. * EUI64 addresses; that should probably be fixed in
  654. * epan/addr_resolv.c.
  655. */
  656. SET_ADDRESS(&pinfo->dl_dst, AT_EUI64, 8, &addr);
  657. SET_ADDRESS(&pinfo->dst, AT_EUI64, 8, &addr);
  658. if (tree) {
  659. proto_tree_add_item(ieee802154_tree, hf_ieee802154_dst64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
  660. proto_item_append_text(proto_root, ", Dst: %s", get_eui64_name(packet->dst64));
  661. }
  662. col_append_fstr(pinfo->cinfo, COL_INFO, ", Dst: %s", get_eui64_name(packet->dst64));
  663. offset += 8;
  664. }
  665. else if (packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE) {
  666. /* Invalid Destination Address Mode. Abort Dissection. */
  667. expert_add_info_format(pinfo, proto_root, PI_MALFORMED, PI_ERROR, "Invalid Destination Address Mode");
  668. pinfo->private_data = pd_save;
  669. return;
  670. }
  671. /* Get the source PAN if it exists. The source address will be present if:
  672. * - The Source addressing exists and
  673. * - The Destination addressing doesn't exist, or the Intra-PAN bit is unset.
  674. */
  675. if ( ((packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) || (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT)) &&
  676. ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) || (!packet->intra_pan)) ) {
  677. /* Source PAN is present, extract it and add it to the tree. */
  678. packet->src_pan = tvb_get_letohs(tvb, offset);
  679. if (tree) {
  680. proto_tree_add_uint(ieee802154_tree, hf_ieee802154_src_panID, tvb, offset, 2, packet->src_pan);
  681. }
  682. offset += 2;
  683. }
  684. else {
  685. /* Set the panID field in case the intra-pan condition was met. */
  686. packet->src_pan = packet->dst_pan;
  687. }
  688. if (ieee_hints) {
  689. ieee_hints->src_pan = packet->src_pan;
  690. }
  691. /* Get short source address if present. */
  692. if (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
  693. char src_addr[32];
  694. /* Get the address. */
  695. packet->src16 = tvb_get_letohs(tvb, offset);
  696. /* Update the Address fields. */
  697. if (packet->src16==IEEE802154_BCAST_ADDR) {
  698. g_snprintf(src_addr, 32, "Broadcast");
  699. }
  700. else {
  701. g_snprintf(src_addr, 32, "0x%04x", packet->src16);
  702. if (!pinfo->fd->flags.visited) {
  703. /* If we know our extended source address from previous packets,
  704. * provide a pointer to it in a hint for upper layers */
  705. addr16.addr = packet->src16;
  706. addr16.pan = packet->src_pan;
  707. if (ieee_hints) {
  708. ieee_hints->src16 = packet->src16;
  709. ieee_hints->map_rec = (ieee802154_map_rec *)
  710. g_hash_table_lookup(ieee802154_map.short_table, &addr16);
  711. }
  712. }
  713. }
  714. TVB_SET_ADDRESS(&pinfo->dl_src, AT_IEEE_802_15_4_SHORT, tvb, offset, 2);
  715. TVB_SET_ADDRESS(&pinfo->src, AT_IEEE_802_15_4_SHORT, tvb, offset, 2);
  716. /* Add the addressing info to the tree. */
  717. if (tree) {
  718. proto_tree_add_uint(ieee802154_tree, hf_ieee802154_src16, tvb, offset, 2, packet->src16);
  719. proto_item_append_text(proto_root, ", Src: %s", src_addr);
  720. if (ieee_hints && ieee_hints->map_rec) {
  721. /* Display inferred source address info */
  722. ti = proto_tree_add_eui64(ieee802154_tree, hf_ieee802154_src64, tvb, offset, 0,
  723. ieee_hints->map_rec->addr64);
  724. PROTO_ITEM_SET_GENERATED(ti);
  725. if ( ieee_hints->map_rec->start_fnum ) {
  726. ti = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_src64_origin, tvb, 0, 0,
  727. ieee_hints->map_rec->start_fnum);
  728. }
  729. else {
  730. ti = proto_tree_add_text(ieee802154_tree, tvb, 0, 0, "Origin: Pre-configured");
  731. }
  732. PROTO_ITEM_SET_GENERATED(ti);
  733. }
  734. }
  735. col_append_fstr(pinfo->cinfo, COL_INFO, ", Src: %s", src_addr);
  736. offset += 2;
  737. }
  738. else if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
  739. static guint64 addr; /* has to be static due to SET_ADDRESS */
  740. /* Get the address. */
  741. packet->src64 = tvb_get_letoh64(tvb, offset);
  742. /* Copy and convert the address to network byte order. */
  743. addr = pntoh64(&(packet->src64));
  744. /* Display the source address. */
  745. /* XXX - OUI resolution doesn't happen when displaying resolved
  746. * EUI64 addresses; that should probably be fixed in
  747. * epan/addr_resolv.c.
  748. */
  749. SET_ADDRESS(&pinfo->dl_src, AT_EUI64, 8, &addr);
  750. SET_ADDRESS(&pinfo->src, AT_EUI64, 8, &addr);
  751. if (tree) {
  752. proto_tree_add_item(ieee802154_tree, hf_ieee802154_src64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
  753. proto_item_append_text(proto_root, ", Src: %s", get_eui64_name(packet->src64));
  754. }
  755. col_append_fstr(pinfo->cinfo, COL_INFO, ", Src: %s", get_eui64_name(packet->src64));
  756. offset += 8;
  757. }
  758. else if (packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE) {
  759. /* Invalid Destination Address Mode. Abort Dissection. */
  760. expert_add_info_format(pinfo, proto_root, PI_MALFORMED, PI_ERROR, "Invalid Source Address Mode");
  761. pinfo->private_data = pd_save;
  762. return;
  763. }
  764. /*=====================================================
  765. * VERIFY FRAME CHECK SEQUENCE
  766. *=====================================================
  767. */
  768. /* Check, but don't display the FCS yet, otherwise the payload dissection
  769. * may be out of place in the tree. But we want to know if the FCS is OK in
  770. * case the CRC is bad (don't want to continue dissection to the NWK layer).
  771. */
  772. if (tvb_bytes_exist(tvb, tvb_reported_length(tvb)-IEEE802154_FCS_LEN, IEEE802154_FCS_LEN)) {
  773. /* The FCS is in the last two bytes of the packet. */
  774. guint16 fcs = tvb_get_letohs(tvb, tvb_reported_length(tvb)-IEEE802154_FCS_LEN);
  775. /* Check if we are expecting a CC2420-style FCS*/
  776. if (options & DISSECT_IEEE802154_OPTION_CC24xx) {
  777. fcs_ok = (fcs & IEEE802154_CC24xx_CRC_OK);
  778. }
  779. else {
  780. guint16 fcs_calc = ieee802154_crc_tvb(tvb, tvb_reported_length(tvb)-IEEE802154_FCS_LEN);
  781. fcs_ok = (fcs == fcs_calc);
  782. }
  783. }
  784. /*=====================================================
  785. * AUXILIARY SECURITY HEADER
  786. *=====================================================
  787. */
  788. /* The Auxiliary Security Header only exists in IEEE 802.15.4-2006 */
  789. if (packet->security_enable && (packet->version == IEEE802154_VERSION_2006)) {
  790. proto_tree *header_tree, *field_tree;
  791. guint8 security_control;
  792. guint aux_length = 5; /* Minimum length of the auxiliary header. */
  793. /* Parse the security control field. */
  794. security_control = tvb_get_guint8(tvb, offset);
  795. packet->security_level = (ieee802154_security_level)(security_control & IEEE802154_AUX_SEC_LEVEL_MASK);
  796. packet->key_id_mode = (ieee802154_key_id_mode)((security_control & IEEE802154_AUX_KEY_ID_MODE_MASK) >> IEEE802154_AUX_KEY_ID_MODE_SHIFT);
  797. /* Compute the length of the auxiliary header and create a subtree. */
  798. if (packet->key_id_mode != KEY_ID_MODE_IMPLICIT) aux_length++;
  799. if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_4) aux_length += 4;
  800. if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_8) aux_length += 8;
  801. ti = proto_tree_add_text(ieee802154_tree, tvb, offset, aux_length, "Auxiliary Security Header");
  802. header_tree = proto_item_add_subtree(ti, ett_ieee802154_auxiliary_security);
  803. /* Security Control Field */
  804. ti = proto_tree_add_text(header_tree, tvb, offset, 1, "Security Control Field (0x%02x)", security_control);
  805. field_tree = proto_item_add_subtree(ti, ett_ieee802154_aux_sec_control);
  806. proto_tree_add_uint(field_tree, hf_ieee802154_security_level, tvb, offset, 1, security_control & IEEE802154_AUX_SEC_LEVEL_MASK);
  807. proto_tree_add_uint(field_tree, hf_ieee802154_key_id_mode, tvb, offset, 1, security_control & IEEE802154_AUX_KEY_ID_MODE_MASK);
  808. proto_tree_add_uint(field_tree, hf_ieee802154_aux_sec_reserved, tvb, offset, 1, security_control & IEEE802154_AUX_KEY_RESERVED_MASK);
  809. offset++;
  810. /* Frame Counter Field */
  811. packet->frame_counter = tvb_get_letohl (tvb, offset);
  812. proto_tree_add_uint(header_tree, hf_ieee802154_aux_sec_frame_counter, tvb, offset,4, packet->frame_counter);
  813. offset +=4;
  814. /* Key identifier field(s). */
  815. if (packet->key_id_mode != KEY_ID_MODE_IMPLICIT) {
  816. /* Create a subtree. */
  817. ti = proto_tree_add_text(header_tree, tvb, offset, 1, "Key Identifier Field"); /* Will fix length later. */
  818. field_tree = proto_item_add_subtree(ti, ett_ieee802154_aux_sec_key_id);
  819. /* Add key source, if it exists. */
  820. if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_4) {
  821. packet->key_source.addr32 = tvb_get_ntohl(tvb, offset);
  822. proto_tree_add_uint64(field_tree, hf_ieee802154_aux_sec_key_source, tvb, offset, 4, packet->key_source.addr32);
  823. proto_item_set_len(ti, 1 + 4);
  824. offset += (int)sizeof (guint32);
  825. }
  826. if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_8) {
  827. packet->key_source.addr64 = tvb_get_ntoh64(tvb, offset);
  828. proto_tree_add_uint64(field_tree, hf_ieee802154_aux_sec_key_source, tvb, offset, 8, packet->key_source.addr64);
  829. proto_item_set_len(ti, 1 + 8);
  830. offset += 8;
  831. }
  832. /* Add key identifier. */
  833. packet->key_index = tvb_get_guint8(tvb, offset);
  834. proto_tree_add_uint(field_tree, hf_ieee802154_aux_sec_key_index, tvb, offset,1, packet->key_index);
  835. offset++;
  836. }
  837. }
  838. /*=====================================================
  839. * NONPAYLOAD FIELDS
  840. *=====================================================
  841. */
  842. /* All of the beacon fields, except the beacon payload are considered nonpayload. */
  843. if (packet->frame_type == IEEE802154_FCF_BEACON) {
  844. /* Parse the superframe spec. */
  845. dissect_ieee802154_superframe(tvb, pinfo, ieee802154_tree, &offset);
  846. /* Parse the GTS information fields. */
  847. dissect_ieee802154_gtsinfo(tvb, pinfo, ieee802154_tree, &offset);
  848. /* Parse the Pending address list. */
  849. dissect_ieee802154_pendaddr(tvb, pinfo, ieee802154_tree, &offset);
  850. }
  851. /* Only the Command ID is considered nonpayload. */
  852. if (packet->frame_type == IEEE802154_FCF_CMD) {
  853. packet->command_id = tvb_get_guint8(tvb, offset);
  854. if (tree) {
  855. proto_tree_add_uint(ieee802154_tree, hf_ieee802154_cmd_id, tvb, offset, 1, packet->command_id);
  856. }
  857. offset++;
  858. /* Display the command identifier in the info column. */
  859. col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
  860. }
  861. /* No other frame types have nonpayload fields. */
  862. /*=====================================================
  863. * PAYLOAD DISSECTION
  864. *=====================================================
  865. */
  866. /* IEEE 802.15.4-2003 may have security information pre-pended to payload */
  867. if (packet->security_enable && (packet->version == IEEE802154_VERSION_2003)) {
  868. /* Store security suite preference in the 2006 security level identifier to simplify 2003 integration! */
  869. packet->security_level = (ieee802154_security_level)ieee802154_sec_suite;
  870. /* Frame Counter and Key Sequence Counter prepended to the payload of an encrypted frame */
  871. if (IEEE802154_IS_ENCRYPTED(packet->security_level)) {
  872. packet->frame_counter = tvb_get_letohl (tvb, offset);
  873. proto_tree_add_uint(ieee802154_tree, hf_ieee802154_sec_frame_counter, tvb, offset, (int)sizeof(guint32), packet->frame_counter);
  874. offset += (int)sizeof(guint32);
  875. packet->key_sequence_counter = tvb_get_guint8 (tvb, offset);
  876. proto_tree_add_uint(ieee802154_tree, hf_ieee802154_sec_key_sequence_counter, tvb, offset, (int)sizeof(guint8), packet->key_sequence_counter);
  877. offset += (int)sizeof(guint8);
  878. }
  879. }
  880. /* Encrypted Payload. */
  881. if (packet->security_enable) {
  882. payload_tvb = dissect_ieee802154_decrypt(tvb, offset, pinfo, packet, &status);
  883. /* Get the unencrypted data if decryption failed. */
  884. if (!payload_tvb) {
  885. /* Deal with possible truncation and the FCS field at the end. */
  886. gint reported_len = tvb_reported_length(tvb)-offset-IEEE802154_FCS_LEN;
  887. gint captured_len = tvb_length(tvb)-offset;
  888. if (reported_len < captured_len) captured_len = reported_len;
  889. payload_tvb = tvb_new_subset(tvb, offset, captured_len, reported_len);
  890. }
  891. /* Display the reason for failure, and abort if the error was fatal. */
  892. switch (status) {
  893. case DECRYPT_PACKET_SUCCEEDED:
  894. case DECRYPT_NOT_ENCRYPTED:
  895. /* No problem. */
  896. break;
  897. case DECRYPT_VERSION_UNSUPPORTED:
  898. /* We don't support decryption with that version of the protocol */
  899. expert_add_info_format(pinfo, proto_root, PI_UNDECODED, PI_WARN, "We don't support decryption with protocol version %u",
  900. packet->version);
  901. call_dissector(data_handle, payload_tvb, pinfo, tree);
  902. goto dissect_ieee802154_fcs;
  903. case DECRYPT_PACKET_TOO_SMALL:
  904. expert_add_info_format(pinfo, proto_root, PI_UNDECODED, PI_WARN, "Packet was too small to include the CRC and MIC");
  905. call_dissector(data_handle, payload_tvb, pinfo, tree);
  906. goto dissect_ieee802154_fcs;
  907. case DECRYPT_PACKET_NO_EXT_SRC_ADDR:
  908. expert_add_info_format(pinfo, proto_root, PI_UNDECODED, PI_WARN, "No extended source address - can't decrypt");
  909. call_dissector(data_handle, payload_tvb, pinfo, tree);
  910. goto dissect_ieee802154_fcs;
  911. case DECRYPT_PACKET_NO_KEY:
  912. expert_add_info_format(pinfo, proto_root, PI_UNDECODED, PI_WARN, "No encryption key set - can't decrypt");
  913. call_dissector(data_handle, payload_tvb, pinfo, tree);
  914. goto dissect_ieee802154_fcs;
  915. case DECRYPT_PACKET_DECRYPT_FAILED:
  916. expert_add_info_format(pinfo, proto_root, PI_UNDECODED, PI_WARN, "Decrypt failed");
  917. call_dissector(data_handle, payload_tvb, pinfo, tree);
  918. goto dissect_ieee802154_fcs;
  919. case DECRYPT_PACKET_MIC_CHECK_FAILED:
  920. expert_add_info_format(pinfo, proto_root, PI_UNDECODED, PI_WARN, "MIC check failed");
  921. /*
  922. * Abort only if the payload was encrypted, in which case we
  923. * probably didn't decrypt the packet right (eg: wrong key).
  924. */
  925. if (IEEE802154_IS_ENCRYPTED(packet->security_level)) {
  926. call_dissector(data_handle, payload_tvb, pinfo, tree);
  927. goto dissect_ieee802154_fcs;
  928. }
  929. break;
  930. }
  931. }
  932. /* Plaintext Payload. */
  933. else {
  934. /* Deal with possible truncation and the FCS field at the end. */
  935. gint reported_len = tvb_reported_length(tvb)-offset-IEEE802154_FCS_LEN;
  936. gint captured_len = tvb_length(tvb)-offset;
  937. if (reported_len < captured_len) captured_len = reported_len;
  938. payload_tvb = tvb_new_subset(tvb, offset, captured_len, reported_len);
  939. }
  940. /*
  941. * Wrap the sub-dissection in a try/catch block in case the payload is
  942. * broken. First we store the current protocol so we can fix it if an
  943. * exception is thrown by the subdissectors.
  944. */
  945. saved_proto = pinfo->current_proto;
  946. /* Try to dissect the payload. */
  947. TRY {
  948. if ((packet->frame_type == IEEE802154_FCF_BEACON) ||
  949. (packet->frame_type == IEEE802154_FCF_DATA)) {
  950. /* Beacon and Data packets contain a payload. */
  951. if ((fcs_ok || !ieee802154_fcs_ok) && (tvb_reported_length(payload_tvb)>0)) {
  952. /* Attempt heuristic subdissection. */
  953. if (!dissector_try_heuristic(ieee802154_heur_subdissector_list, payload_tvb, pinfo, tree, NULL)) {
  954. /* Could not subdissect, call the data dissector instead. */
  955. call_dissector(data_handle, payload_tvb, pinfo, tree);
  956. }
  957. }
  958. else {
  959. /* If no sub-dissector was called, call the data dissector. */
  960. call_dissector(data_handle, payload_tvb, pinfo, tree);
  961. }
  962. }
  963. /* If the packet is a command, try to dissect the payload. */
  964. else if (packet->frame_type == IEEE802154_FCF_CMD) {
  965. switch (packet->command_id) {
  966. case IEEE802154_CMD_ASRQ:
  967. IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
  968. (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
  969. (packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE));
  970. dissect_ieee802154_assoc_req(payload_tvb, pinfo, ieee802154_tree, packet);
  971. break;
  972. case IEEE802154_CMD_ASRSP:
  973. IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
  974. (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
  975. (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT));
  976. dissect_ieee802154_assoc_rsp(payload_tvb, pinfo, ieee802154_tree, packet);
  977. break;
  978. case IEEE802154_CMD_DISAS:
  979. IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
  980. (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
  981. (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT));
  982. dissect_ieee802154_disassoc(payload_tvb, pinfo, ieee802154_tree, packet);
  983. break;
  984. case IEEE802154_CMD_DATA_RQ:
  985. IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id, packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE);
  986. /* No payload expected. */
  987. break;
  988. case IEEE802154_CMD_PANID_ERR:
  989. IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
  990. (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
  991. (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT));
  992. /* No payload expected. */
  993. break;
  994. case IEEE802154_CMD_ORPH_NOTIF:
  995. IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
  996. (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
  997. (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&
  998. (packet->dst16 == IEEE802154_BCAST_ADDR) &&
  999. (packet->src_pan == IEEE802154_BCAST_PAN) &&
  1000. (packet->dst_pan == IEEE802154_BCAST_PAN));
  1001. /* No payload expected. */
  1002. break;
  1003. case IEEE802154_CMD_BCN_RQ:
  1004. IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
  1005. (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&
  1006. (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE) &&
  1007. (packet->dst16 == IEEE802154_BCAST_ADDR) &&
  1008. (packet->dst_pan == IEEE802154_BCAST_PAN));
  1009. /* No payload expected. */
  1010. break;
  1011. case IEEE802154_CMD_COORD_REAL:
  1012. IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
  1013. (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
  1014. (packet->dst_pan == IEEE802154_BCAST_PAN) &&
  1015. (packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE));
  1016. if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
  1017. /* If directed to a 16-bit address, check that it is being broadcast. */
  1018. IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id, packet->dst16 == IEEE802154_BCAST_ADDR);
  1019. }
  1020. dissect_ieee802154_realign(payload_tvb, pinfo, ieee802154_tree, packet);
  1021. break;
  1022. case IEEE802154_CMD_GTS_REQ:
  1023. /* Check that the addressing is correct for this command type. */
  1024. IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
  1025. (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&
  1026. (packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) &&
  1027. (packet->src16 != IEEE802154_BCAST_ADDR) &&
  1028. (packet->src16 != IEEE802154_NO_ADDR16));
  1029. dissect_ieee802154_gtsreq(payload_tvb, pinfo, ieee802154_tree, packet);
  1030. break;
  1031. default:
  1032. /* Unknown Command */
  1033. call_dissector(data_handle, payload_tvb, pinfo, ieee802154_tree);
  1034. break;
  1035. } /* switch */
  1036. }
  1037. /* Otherwise, dump whatever is left over to the data dissector. */
  1038. else {
  1039. call_dissector(data_handle, payload_tvb, pinfo, tree);
  1040. }
  1041. }
  1042. CATCH_ALL {
  1043. /*
  1044. * Someone encountered an error while dissecting the payload. But
  1045. * we haven't yet finished processing all of our layer. Catch and
  1046. * display the exception, then fall-through to finish displaying
  1047. * the FCS (which we display last so the frame is ordered correctly
  1048. * in the tree).
  1049. */
  1050. show_exception(payload_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
  1051. pinfo->current_proto = saved_proto;
  1052. }
  1053. ENDTRY;
  1054. /*=====================================================
  1055. * FRAME CHECK SEQUENCE
  1056. *=====================================================
  1057. */
  1058. dissect_ieee802154_fcs:
  1059. /* The FCS should be the last bytes of the reported packet. */
  1060. offset = tvb_reported_length(tvb)-IEEE802154_FCS_LEN;
  1061. /* Dissect the FCS only if it exists (captures which don't or can't get the
  1062. * FCS will simply truncate the packet to omit it, but should still set the
  1063. * reported length to cover the original packet length), so if the snapshot
  1064. * is too short for an FCS don't make a fuss.
  1065. */
  1066. if (tvb_bytes_exist(tvb, offset, IEEE802154_FCS_LEN) && (tree)) {
  1067. proto_tree *field_tree;
  1068. guint16 fcs = tvb_get_letohs(tvb, offset);
  1069. /* Display the FCS depending on expected FCS format */
  1070. if ((options & DISSECT_IEEE802154_OPTION_CC24xx)) {
  1071. /* Create a subtree for the FCS. */
  1072. ti = proto_tree_add_text(ieee802154_tree, tvb, offset, 2, "Frame Check Sequence (TI CC24xx format): FCS %s", (fcs_ok) ? "OK" : "Bad");
  1073. field_tree = proto_item_add_subtree(ti, ett_ieee802154_fcs);
  1074. /* Display FCS contents. */
  1075. ti = proto_tree_add_int(field_tree, hf_ieee802154_rssi, tvb, offset++, 1, (gint8) (fcs & IEEE802154_CC24xx_RSSI));
  1076. proto_item_append_text(ti, " dB"); /* Displaying Units */
  1077. proto_tree_add_boolean(field_tree, hf_ieee802154_fcs_ok, tvb, offset, 1, (gboolean) (fcs & IEEE802154_CC24xx_CRC_OK));
  1078. proto_tree_add_uint(field_tree, hf_ieee802154_correlation, tvb, offset, 1, (guint8) ((fcs & IEEE802154_CC24xx_CORRELATION) >> 8));
  1079. }
  1080. else {
  1081. ti = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_fcs, tvb, offset, 2, fcs);
  1082. if (fcs_ok) {
  1083. proto_item_append_text(ti, " (Correct)");
  1084. }
  1085. else {
  1086. proto_item_append_text(ti, " (Incorrect, expected FCS=0x%04x", ieee802154_crc_tvb(tvb, offset));
  1087. }
  1088. /* To Help with filtering, add the fcs_ok field to the tree. */
  1089. ti = proto_tree_add_boolean(ieee802154_tree, hf_ieee802154_fcs_ok, tvb, offset, 2, fcs_ok);
  1090. PROTO_ITEM_SET_HIDDEN(ti);
  1091. }
  1092. }
  1093. else if (tree) {
  1094. /* Even if the FCS isn't present, add the fcs_ok field to the tree to
  1095. * help with filter. Be sure not to make it visible though.
  1096. */
  1097. ti = proto_tree_add_boolean_format_value(ieee802154_tree, hf_ieee802154_fcs_ok, tvb, offset, 2, fcs_ok, "Unknown");
  1098. PROTO_ITEM_SET_HIDDEN(ti);
  1099. }
  1100. /* If the CRC is invalid, make a note of it in the info column. */
  1101. if (!fcs_ok) {
  1102. col_append_str(pinfo->cinfo, COL_INFO, ", Bad FCS");
  1103. if (tree) proto_item_append_text(proto_root, ", Bad FCS");
  1104. /* Flag packet as having a bad crc. */
  1105. expert_add_info_format(pinfo, proto_root, PI_CHECKSUM, PI_WARN, "Bad FCS");
  1106. }
  1107. pinfo->private_data = pd_save;
  1108. } /* dissect_ieee802154_common */
  1109. /*FUNCTION:------------------------------------------------------
  1110. * NAME
  1111. * dissect_ieee802154_superframe
  1112. * DESCRIPTION
  1113. * Subdissector command for the Superframe specification
  1114. * sub-field within the beacon frame.
  1115. * PARAMETERS
  1116. * tvbuff_t *tvb - pointer to buffer containing raw packet.
  1117. * packet_info *pinfo - pointer to packet information fields (unused).
  1118. * proto_tree *tree - pointer to command subtree.
  1119. * ieee802154_packet *packet - IEEE 802.15.4 packet information (unused).
  1120. * guint *offset - offset into the tvbuff to begin dissection.
  1121. * RETURNS
  1122. * void
  1123. *---------------------------------------------------------------
  1124. */
  1125. static void
  1126. dissect_ieee802154_superframe(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint *offset)
  1127. {
  1128. proto_tree *field_tree = NULL;
  1129. proto_item *ti;
  1130. guint16 superframe;
  1131. /* Parse the superframe spec. */
  1132. superframe = tvb_get_letohs(tvb, *offset);
  1133. if (tree) {
  1134. /* Add Subtree for superframe specification */
  1135. ti = proto_tree_add_text(tree, tvb, *offset, 2, "Superframe Specification");
  1136. field_tree = proto_item_add_subtree(ti, ett_ieee802154_superframe);
  1137. /* Add Beacon Order to the superframe spec. */
  1138. proto_tree_add_uint(field_tree, hf_ieee802154_beacon_order, tvb, *offset, 2, superframe & IEEE802154_BEACON_ORDER_MASK);
  1139. proto_tree_add_uint(field_tree, hf_ieee802154_superframe_order, tvb, *offset, 2, superframe & IEEE802154_SUPERFRAME_ORDER_MASK);
  1140. proto_tree_add_uint(field_tree, hf_ieee802154_cap, tvb, *offset, 2, superframe & IEEE802154_SUPERFRAME_CAP_MASK);
  1141. proto_tree_add_boolean(field_tree, hf_ieee802154_superframe_battery_ext, tvb, *offset, 2, superframe & IEEE802154_BATT_EXTENSION_MASK);
  1142. proto_tree_add_boolean(field_tree, hf_ieee802154_superframe_coord, tvb, *offset, 2, superframe & IEEE802154_SUPERFRAME_COORD_MASK);
  1143. proto_tree_add_boolean(field_tree, hf_ieee802154_assoc_permit, tvb, *offset, 2, superframe & IEEE802154_ASSOC_PERMIT_MASK);
  1144. }
  1145. (*offset) += 2;
  1146. } /* dissect_ieee802154_superframe */
  1147. /*FUNCTION:------------------------------------------------------
  1148. * NAME
  1149. * dissect_ieee802154_gtsinfo
  1150. * DESCRIPTION
  1151. * Subdissector command for the GTS information fields within
  1152. * the beacon frame.
  1153. * PARAMETERS
  1154. * tvbuff_t *tvb - pointer to buffer containing raw packet.
  1155. * packet_info *pinfo - pointer to packet information fields (unused).
  1156. * proto_tree *tree - pointer to command subtree.
  1157. * ieee802154_packet *packet - IEEE 802.15.4 packet information (unused).
  1158. * guint *offset - offset into the tvbuff to begin dissection.
  1159. * RETURNS
  1160. * void
  1161. *---------------------------------------------------------------
  1162. */
  1163. static void
  1164. dissect_ieee802154_gtsinfo(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint *offset)
  1165. {
  1166. proto_tree *field_tree = NULL;
  1167. proto_tree *subtree = NULL;
  1168. proto_item *ti;
  1169. guint8 gts_spec;
  1170. guint8 gts_count;
  1171. /* Get and display the GTS specification field */
  1172. gts_spec = tvb_get_guint8(tvb, *offset);
  1173. gts_count = gts_spec & IEEE802154_GTS_COUNT_MASK;
  1174. if (tree) {
  1175. /* Add Subtree for GTS information. */
  1176. if (gts_count) {
  1177. ti = proto_tree_add_text(tree, tvb, *offset, 2 + (gts_count * 3), "GTS");
  1178. }
  1179. else {
  1180. ti = proto_tree_add_text(tree, tvb, *offset, 1, "GTS");
  1181. }
  1182. field_tree = proto_item_add_subtree(ti, ett_ieee802154_gts);
  1183. proto_tree_add_uint(field_tree, hf_ieee802154_gts_count, tvb, *offset, 1, gts_count);
  1184. proto_tree_add_boolean(field_tree, hf_ieee802154_gts_permit, tvb, *offset, 1, gts_spec & IEEE802154_GTS_PERMIT_MASK);
  1185. }
  1186. (*offset) += 1;
  1187. /* If the GTS descriptor count is nonzero, then the GTS directions mask and descriptor list are present. */
  1188. if (gts_count) {
  1189. guint8 gts_directions = tvb_get_guint8(tvb, *offset);
  1190. guint gts_rx = 0;
  1191. int i;
  1192. /* Display the directions mask. */
  1193. if (tree) {
  1194. proto_tree *dir_tree = NULL;
  1195. /* Create a subtree. */
  1196. ti = proto_tree_add_text(field_tree, tvb, *offset, 1, "GTS Directions");
  1197. dir_tree = proto_item_add_subtree(ti, ett_ieee802154_gts_direction);
  1198. /* Add the directions to the subtree. */
  1199. for (i=0; i<gts_count; i++) {
  1200. gboolean dir = gts_directions & IEEE802154_GTS_DIRECTION_SLOT(i);
  1201. 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");
  1202. if (dir) gts_rx++;
  1203. } /* for */
  1204. proto_item_append_text(ti, ": %i Receive & %i Transmit", gts_rx, gts_count - gts_rx);
  1205. }
  1206. (*offset) += 1;
  1207. /* Create a subtree for the GTS descriptors. */
  1208. if (tree) {
  1209. ti = proto_tree_add_text(field_tree, tvb, *offset, gts_count * 3, "GTS Descriptors");
  1210. subtree = proto_item_add_subtree(ti, ett_ieee802154_gts_descriptors);
  1211. }
  1212. /* Get and display the GTS descriptors. */
  1213. for (i=0; i<gts_count; i++) {
  1214. guint16 gts_addr = tvb_get_letohs(tvb, (*offset));
  1215. guint8 gts_slot = tvb_get_guint8(tvb, (*offset)+2);
  1216. guint8 gts_length = (gts_slot & IEEE802154_GTS_LENGTH_MASK) >> IEEE802154_GTS_LENGTH_SHIFT;
  1217. if (tree) {
  1218. /* Add address, slot, and time length fields. */
  1219. ti = proto_tree_add_text(subtree, tvb, (*offset), 3, "{Address: 0x%04x", gts_addr);
  1220. proto_item_append_text(ti, ", Slot: %i", gts_slot);
  1221. proto_item_append_text(ti, ", Length: %i}", gts_length);
  1222. }
  1223. (*offset) += 3;
  1224. } /* for */
  1225. }
  1226. } /* dissect_ieee802154_gtsinfo */
  1227. /*FUNCTION:------------------------------------------------------
  1228. * NAME
  1229. * dissect_ieee802154_pendaddr
  1230. * DESCRIPTION
  1231. * Subdissector command for the pending address list fields
  1232. * within the beacon frame.
  1233. * PARAMETERS
  1234. * tvbuff_t *tvb - pointer to buffer containing raw packet.
  1235. * packet_info *pinfo - pointer to packet information fields (unused).
  1236. * proto_tree *tree - pointer to command subtree.
  1237. * ieee802154_packet *packet - IEEE 802.15.4 packet information (unused).
  1238. * guint *offset - offset into the tvbuff to begin dissection.
  1239. * RETURNS
  1240. * void
  1241. *---------------------------------------------------------------
  1242. */
  1243. static void
  1244. dissect_ieee802154_pendaddr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint *offset)
  1245. {
  1246. proto_tree *subtree = NULL;
  1247. proto_item *ti;
  1248. guint8 pend_spec;
  1249. guint8 pend_num16;
  1250. guint8 pend_num64;
  1251. int i;
  1252. /* Get the Pending Addresses specification fields */
  1253. pend_spec = tvb_get_guint8(tvb, *offset);
  1254. pend_num16 = pend_spec & IEEE802154_PENDADDR_SHORT_MASK;
  1255. pend_num64 = (pend_spec & IEEE802154_PENDADDR_LONG_MASK) >> IEEE802154_PENDADDR_LONG_SHIFT;
  1256. if (tree) {
  1257. /* Add Subtree for the addresses */
  1258. ti = proto_tree_add_text(tree, tvb, *offset, 1 + 2*pend_num16 + 8*pend_num64, "Pending Addresses: %i Short and %i Long", pend_num16, pend_num64);
  1259. subtree = proto_item_add_subtree(ti, ett_ieee802154_pendaddr);
  1260. }
  1261. (*offset) += 1;
  1262. for (i=0; i<pend_num16; i++) {
  1263. guint16 addr = tvb_get_letohs(tvb, *offset);
  1264. proto_tree_add_uint(subtree, hf_ieee802154_pending16, tvb, *offset, 2, addr);
  1265. (*offset) += 2;
  1266. } /* for */
  1267. for (i=0; i<pend_num64; i++) {
  1268. proto_tree_add_item(subtree, hf_ieee802154_pending64, tvb, *offset, 8, ENC_LITTLE_ENDIAN);
  1269. (*offset) += 8;
  1270. } /* for */
  1271. } /* dissect_ieee802154_pendaddr */
  1272. /*FUNCTION:------------------------------------------------------
  1273. * NAME
  1274. * dissect_ieee802154_assoc_req
  1275. * DESCRIPTION
  1276. * Command subdissector routine for the Association request
  1277. * command.
  1278. * PARAMETERS
  1279. * tvbuff_t *tvb - pointer to buffer containing raw packet.
  1280. * packet_info *pinfo - pointer to packet information fields.
  1281. * proto_tree *tree - pointer to protocol tree.
  1282. * ieee802154_packet *packet - IEEE 802.15.4 packet information.
  1283. * RETURNS
  1284. * void
  1285. *---------------------------------------------------------------
  1286. */
  1287. static void
  1288. dissect_ieee802154_assoc_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
  1289. {
  1290. proto_tree *subtree = NULL;
  1291. proto_item * ti;
  1292. guint8 capability;
  1293. /* Create a subtree for this command frame. */
  1294. if (tree) {
  1295. ti = proto_tree_add_text(tree, tvb, 0, 1, "%s", val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
  1296. subtree = proto_item_add_subtree(ti, ett_ieee802154_cmd);
  1297. }
  1298. /* Get and display capability info. */
  1299. capability = tvb_get_guint8(tvb, 0);
  1300. if (tree) {
  1301. /* Enter the capability bits. */
  1302. proto_tree_add_boolean(subtree, hf_ieee802154_cinfo_alt_coord, tvb, 0, 1, capability & IEEE802154_CMD_CINFO_ALT_PAN_COORD);
  1303. ti = proto_tree_add_boolean(subtree, hf_ieee802154_cinfo_device_type, tvb, 0, 1, capability & IEEE802154_CMD_CINFO_DEVICE_TYPE);
  1304. if (capability & IEEE802154_CMD_CINFO_DEVICE_TYPE) proto_item_append_text(ti, " (FFD)");
  1305. else proto_item_append_text(ti, " (RFD)");
  1306. ti = proto_tree_add_boolean(subtree, hf_ieee802154_cinfo_power_src, tvb, 0, 1, capability & IEEE802154_CMD_CINFO_POWER_SRC);
  1307. if (capability & IEEE802154_CMD_CINFO_POWER_SRC) proto_item_append_text(ti, " (AC/Mains Power)");
  1308. else proto_item_append_text(ti, " (Battery)");
  1309. proto_tree_add_boolean(subtree, hf_ieee802154_cinfo_idle_rx, tvb, 0, 1, capability & IEEE802154_CMD_CINFO_IDLE_RX);
  1310. proto_tree_add_boolean(subtree, hf_ieee802154_cinfo_sec_capable, tvb, 0, 1, capability & IEEE802154_CMD_CINFO_SEC_CAPABLE);
  1311. proto_tree_add_boolean(subtree, hf_ieee802154_cinfo_alloc_addr, tvb, 0, 1, capability & IEEE802154_CMD_CINFO_ALLOC_ADDR);
  1312. }
  1313. /* Call the data dissector for any leftover bytes. */
  1314. if (tvb_length(tvb) > 1) {
  1315. call_dissector(data_handle, tvb_new_subset_remaining(tvb, 1), pinfo, tree);
  1316. }
  1317. } /* dissect_ieee802154_assoc_req */
  1318. /*FUNCTION:------------------------------------------------------
  1319. * NAME
  1320. * dissect_ieee802154_assoc_rsp
  1321. * DESCRIPTION
  1322. * Command subdissector routine for the Association response
  1323. * command.
  1324. * PARAMETERS
  1325. * tvbuff_t *tvb - pointer to buffer containing raw packet.
  1326. * packet_info *pinfo - pointer to packet information fields.
  1327. * proto_tree *tree - pointer to protocol tree.
  1328. * ieee802154_packet *packet - IEEE 802.15.4 packet information.
  1329. * RETURNS
  1330. * void
  1331. *---------------------------------------------------------------
  1332. */
  1333. static void
  1334. dissect_ieee802154_assoc_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
  1335. {
  1336. proto_tree *subtree = NULL;
  1337. proto_item *ti;
  1338. guint16 short_addr;
  1339. guint8 status;
  1340. guint offset = 0;
  1341. /* Create a subtree for this command frame. */
  1342. if (tree) {
  1343. ti = proto_tree_add_text(tree, tvb, offset, 3, "%s", val_to_str_const(packet->command_id,
  1344. ieee802154_cmd_names, "Unknown Command"));
  1345. subtree = proto_item_add_subtree(ti, ett_ieee802154_cmd);
  1346. }
  1347. /* Get and display the short address. */
  1348. short_addr = tvb_get_letohs(tvb, offset);
  1349. if (tree) {
  1350. proto_tree_add_uint(subtree, hf_ieee802154_assoc_addr, tvb, offset, 2, short_addr);
  1351. }
  1352. offset += 2;
  1353. /* Get and display the status. */
  1354. status = tvb_get_guint8(tvb, offset);
  1355. if (tree) {
  1356. ti = proto_tree_add_uint(subtree, hf_ieee802154_assoc_status, tvb, offset, 1, status);
  1357. if (status == IEEE802154_CMD_ASRSP_AS_SUCCESS) proto_item_append_text(ti, " (Association Successful)");
  1358. else if (status == IEEE802154_CMD_ASRSP_PAN_FULL) proto_item_append_text(ti, " (PAN Full)");
  1359. else if (status == IEEE802154_CMD_ASRSP_PAN_DENIED) proto_item_append_text(ti, " (Association Denied)");
  1360. else proto_item_append_text(ti, " (Reserved)");
  1361. }
  1362. offset += 1;
  1363. /* Update the info column. */
  1364. if (status == IEEE802154_CMD_ASRSP_AS_SUCCESS) {
  1365. /* Association was successful. */
  1366. if (packet->src_addr_mode != IEEE802154_FCF_ADDR_SHORT) {
  1367. col_append_fstr(pinfo->cinfo, COL_INFO, ", PAN: 0x%04x", packet->dst_pan);
  1368. }
  1369. if (short_addr != IEEE802154_NO_ADDR16) {
  1370. col_append_fstr(pinfo->cinfo, COL_INFO, " Addr: 0x%04x", short_addr);
  1371. }
  1372. }
  1373. else {
  1374. /* Association was unsuccessful. */
  1375. col_append_fstr(pinfo->cinfo, COL_INFO, ", Unsuccessful");
  1376. }
  1377. /* Update the address table. */
  1378. if ((status == IEEE802154_CMD_ASRSP_AS_SUCCESS) && (short_addr != IEEE802154_NO_ADDR16)) {
  1379. ieee802154_addr_update(&ieee802154_map, short_addr, packet->dst_pan, packet->dst64,
  1380. pinfo->current_proto, pinfo->fd->num);
  1381. }
  1382. /* Call the data dissector for any leftover bytes. */
  1383. if (tvb_length(tvb) > offset) {
  1384. call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree);
  1385. }
  1386. } /* dissect_ieee802154_assoc_rsp */
  1387. /*FUNCTION:------------------------------------------------------
  1388. * NAME
  1389. * dissect_ieee802154_disassoc
  1390. * DESCRIPTION
  1391. * Command subdissector routine for the Disassociate command.
  1392. * PARAMETERS
  1393. * tvbuff_t *tvb - pointer to buffer containing raw packet.
  1394. * packet_info *pinfo - pointer to packet information fields.
  1395. * proto_tree *tree - pointer to protocol tree.
  1396. * ieee802154_packet *packet - IEEE 802.15.4 packet information.
  1397. * RETURNS
  1398. * void
  1399. *---------------------------------------------------------------
  1400. */
  1401. static void
  1402. dissect_ieee802154_disassoc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
  1403. {
  1404. proto_tree *subtree = NULL;
  1405. proto_item *ti;
  1406. guint8 reason;
  1407. /* Create a subtree for this command frame. */
  1408. if (tree) {
  1409. ti = proto_tree_add_text(tree, tvb, 0, 1, "%s", val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
  1410. subtree = proto_item_add_subtree(ti, ett_ieee802154_cmd);
  1411. }
  1412. /* Get and display the disassociation reason. */
  1413. reason = tvb_get_guint8(tvb, 0);
  1414. if (tree) {
  1415. ti = proto_tree_add_uint(subtree, hf_ieee802154_disassoc_reason, tvb, 0, 1, reason);
  1416. switch(reason) {
  1417. case 0x01:
  1418. proto_item_append_text(ti, " (Coordinator requests device to leave)");
  1419. break;
  1420. case 0x02:
  1421. proto_item_append_text(ti, " (Device wishes to leave)");
  1422. break;
  1423. default:
  1424. proto_item_append_text(ti, " (Reserved)");
  1425. break;
  1426. } /* switch */
  1427. }
  1428. if (!pinfo->fd->flags.visited) {
  1429. /* Update the address tables */
  1430. if ( packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT ) {
  1431. ieee802154_long_addr_invalidate(packet->dst64, pinfo->fd->num);
  1432. } else if ( packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT ) {
  1433. ieee802154_short_addr_invalidate(packet->dst16, packet->dst_pan, pinfo->fd->num);
  1434. }
  1435. }
  1436. /* Call the data dissector for any leftover bytes. */
  1437. if (tvb_length(tvb) > 1) {
  1438. call_dissector(data_handle, tvb_new_subset_remaining(tvb, 1), pinfo, tree);
  1439. }
  1440. } /* dissect_ieee802154_disassoc */
  1441. /*FUNCTION:------------------------------------------------------
  1442. * NAME
  1443. * dissect_ieee802154_realign
  1444. * DESCRIPTION
  1445. * Command subdissector routine for the Coordinator Realignment
  1446. * command.
  1447. * PARAMETERS
  1448. * tvbuff_t *tvb - pointer to buffer containing raw packet.
  1449. * packet_info *pinfo - pointer to packet information fields.
  1450. * proto_tree *tree - pointer to protocol tree.
  1451. * ieee802154_packet *packet - IEEE 802.15.4 packet information.
  1452. * RETURNS
  1453. * void
  1454. *---------------------------------------------------------------
  1455. */
  1456. static void
  1457. dissect_ieee802154_realign(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
  1458. {
  1459. proto_tree *subtree = NULL;
  1460. proto_item *ti;
  1461. guint16 pan_id;
  1462. guint16 coord_addr;
  1463. guint8 channel;
  1464. guint16 short_addr;
  1465. guint offset = 0;
  1466. /* Create a subtree for this command frame. */
  1467. if (tree) {
  1468. ti = proto_tree_add_text(tree, tvb, offset, 0, "%s", val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
  1469. subtree = proto_item_add_subtree(ti, ett_ieee802154_cmd);
  1470. }
  1471. /* Get and display the command PAN ID. */
  1472. pan_id = tvb_get_letohs(tvb, offset);
  1473. proto_tree_add_uint(subtree, hf_ieee802154_realign_pan, tvb, offset, 2, pan_id);
  1474. col_append_fstr(pinfo->cinfo, COL_INFO, ", PAN: 0x%04x", pan_id);
  1475. offset += 2;
  1476. /* Get and display the coordinator address. */
  1477. coord_addr = tvb_get_letohs(tvb, offset);
  1478. proto_tree_add_uint(subtree, hf_ieee802154_realign_caddr, tvb, offset, 2, coord_addr);
  1479. col_append_fstr(pinfo->cinfo, COL_INFO, ", Coordinator: 0x%04x", coord_addr);
  1480. offset += 2;
  1481. /* Get and display the channel. */
  1482. channel = tvb_get_guint8(tvb, offset);
  1483. proto_tree_add_uint(subtree, hf_ieee802154_realign_channel, tvb, offset, 1, channel);
  1484. col_append_fstr(pinfo->cinfo, COL_INFO, ", Channel: %u", channel);
  1485. offset += 1;
  1486. /* Get and display the short address. */
  1487. short_addr = tvb_get_letohs(tvb, offset);
  1488. if (tree) proto_tree_add_uint(subtree, hf_ieee802154_realign_addr, tvb, offset, 2, short_addr);
  1489. if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT)
  1490. && (short_addr != IEEE802154_NO_ADDR16)) {
  1491. col_append_fstr(pinfo->cinfo, COL_INFO, ", Addr: 0x%04x", short_addr);
  1492. }
  1493. offset += 2;
  1494. /* Update the address table. */
  1495. if ((short_addr != IEEE802154_NO_ADDR16) && (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT)) {
  1496. ieee802154_addr_update(&ieee802154_map, short_addr, packet->dst_pan, packet->dst64,
  1497. pinfo->current_proto, pinfo->fd->num);
  1498. }
  1499. /* Get and display the channel page, if it exists. Added in IEEE802.15.4-2006 */
  1500. if (tvb_bytes_exist(tvb, offset, 1)) {
  1501. guint8 channel_page = tvb_get_guint8(tvb, offset);
  1502. if (tree) proto_tree_add_uint(subtree, hf_ieee802154_realign_channel_page, tvb, offset, 1, channel_page);
  1503. offset += 1;
  1504. }
  1505. /* Fix the length of the command subtree. */
  1506. if (tree) {
  1507. proto_item_set_len(subtree, offset);
  1508. }
  1509. /* Call the data dissector for any leftover bytes. */
  1510. if (tvb_length(tvb) > offset) {
  1511. call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree);
  1512. }
  1513. } /* dissect_ieee802154_realign */
  1514. /*FUNCTION:------------------------------------------------------
  1515. * NAME
  1516. * dissect_ieee802154_gtsreq
  1517. * DESCRIPTION
  1518. * Command subdissector routine for the GTS request command.
  1519. *
  1520. * Assumes that COL_INFO will be set to the command name,
  1521. * command name will already be appended to the command subtree
  1522. * and protocol root. In addition, assumes that the command ID
  1523. * has already been parsed.
  1524. * PARAMETERS
  1525. * tvbuff_t *tvb - pointer to buffer containing raw packet.
  1526. * packet_info *pinfo - pointer to packet information fields (unused).
  1527. * proto_tree *tree - pointer to protocol tree.
  1528. * ieee802154_packet *packet - IEEE 802.15.4 packet information (unused).
  1529. * RETURNS
  1530. * void
  1531. *---------------------------------------------------------------
  1532. */
  1533. static void
  1534. dissect_ieee802154_gtsreq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
  1535. {
  1536. proto_tree *subtree = NULL;
  1537. proto_item *ti;
  1538. guint8 characteristics;
  1539. guint8 length;
  1540. guint8 direction;
  1541. guint8 type;
  1542. /* Create a subtree for this command frame. */
  1543. if (tree) {
  1544. ti = proto_tree_add_text(tree, tvb, 0, 1, "%s", val_to_str_const(packet->command_id, ieee802154_cmd_names,
  1545. "Unknown Command"));
  1546. subtree = proto_item_add_subtree(ti, ett_ieee802154_cmd);
  1547. }
  1548. /* Get the characteristics field. */
  1549. characteristics = tvb_get_guint8(tvb, 0);
  1550. length = characteristics & IEEE802154_CMD_GTS_REQ_LEN;
  1551. direction = characteristics & IEEE802154_CMD_GTS_REQ_DIR;
  1552. type = characteristics & IEEE802154_CMD_GTS_REQ_TYPE;
  1553. /* Display the characteristics field. */
  1554. if (tree) {
  1555. proto_tree_add_uint(subtree, hf_ieee802154_gtsreq_len, tvb, 0, 1, length);
  1556. ti = proto_tree_add_boolean(subtree, hf_ieee802154_gtsreq_dir, tvb, 0, 1, direction);
  1557. if (direction) proto_item_append_text(ti, " (Receive)");
  1558. else proto_item_append_text(ti, " (Transmit)");
  1559. ti = proto_tree_add_boolean(subtree, hf_ieee802154_gtsreq_type, tvb, 0, 1, type);
  1560. if (type) proto_item_append_text(ti, " (Allocate GTS)");
  1561. else proto_item_append_text(ti, " (Deallocate GTS)");
  1562. }
  1563. /* Call the data dissector for any leftover bytes. */
  1564. if (tvb_length(tvb) > 1) {
  1565. call_dissector(data_handle, tvb_new_subset_remaining(tvb, 1), pinfo, tree);
  1566. }
  1567. } /* dissect_ieee802154_gtsreq */
  1568. /*FUNCTION:------------------------------------------------------
  1569. * NAME
  1570. * dissect_ieee802154_decrypt
  1571. * DESCRIPTION
  1572. * IEEE 802.15.4 decryption algorithm. Tries to find the
  1573. * appropriate key from the information in the IEEE 802.15.4
  1574. * packet structure and dissector config.
  1575. *
  1576. * This function implements the security proceedures for the
  1577. * 2006 version of the spec only. IEEE 802.15.4-2003 is
  1578. * unsupported.
  1579. * PARAMETERS
  1580. * tvbuff_t *tvb - IEEE 802.15.4 packet.
  1581. * packet_info * pinfo - Packet info structure.
  1582. * guint offset - Offset where the ciphertext 'c' starts.
  1583. * ieee802154_packet *packet - IEEE 802.15.4 packet information.
  1584. * ws_decrypt_status *status - status of decryption returned through here on failure.
  1585. * RETURNS
  1586. * tvbuff_t * - Decrypted payload.
  1587. *---------------------------------------------------------------
  1588. */
  1589. static tvbuff_t *
  1590. dissect_ieee802154_decrypt(tvbuff_t * tvb, guint offset, packet_info * pinfo, ieee802154_packet * packet, ws_decrypt_status * status)
  1591. {
  1592. tvbuff_t * ptext_tvb;
  1593. gboolean have_mic = FALSE;
  1594. guint64 srcAddr;
  1595. unsigned char key[16];
  1596. unsigned char tmp[16];
  1597. unsigned char rx_mic[16];
  1598. guint M;
  1599. gint captured_len;
  1600. gint reported_len;
  1601. ieee802154_hints_t *ieee_hints;
  1602. /*
  1603. * Check the version; we only support IEEE 802.15.4-2003 and IEEE 802.15.4-2006.
  1604. * We must do this first, as, if this isn't IEEE 802.15.4-2003 or IEEE 802.15.4-2006,
  1605. * we don't have the Auxiliary Security Header, and haven't
  1606. * filled in the information for it, and none of the stuff
  1607. * we do afterwards, which uses that information, is doable.
  1608. */
  1609. if ((packet->version != IEEE802154_VERSION_2006) && (packet->version != IEEE802154_VERSION_2003)) {
  1610. *status = DECRYPT_VERSION_UNSUPPORTED;
  1611. return NULL;
  1612. }
  1613. ieee_hints = (ieee802154_hints_t *)p_get_proto_data(pinfo->fd, proto_ieee802154, 0);
  1614. /* Get the captured and on-the-wire length of the payload. */
  1615. M = IEEE802154_MIC_LENGTH(packet->security_level);
  1616. reported_len = tvb_reported_length_remaining(tvb, offset) - IEEE802154_FCS_LEN - M;
  1617. if (reported_len < 0) {
  1618. *status = DECRYPT_PACKET_TOO_SMALL;
  1619. return NULL;
  1620. }
  1621. /* Check of the payload is truncated. */
  1622. if (tvb_bytes_exist(tvb, offset, reported_len)) {
  1623. captured_len = reported_len;
  1624. }
  1625. else {
  1626. captured_len = tvb_length_remaining(tvb, offset);
  1627. }
  1628. /* Check if the MIC is present in the captured data. */
  1629. have_mic = tvb_bytes_exist(tvb, offset + reported_len, M);
  1630. if (have_mic) {
  1631. tvb_memcpy(tvb, rx_mic, offset + reported_len, M);
  1632. }
  1633. /*=====================================================
  1634. * Key Lookup - Need to find the appropriate key.
  1635. *=====================================================
  1636. */
  1637. /*
  1638. * Oh God! The specification is so bad. This is the worst
  1639. * case of design-by-committee I've ever seen in my life.
  1640. * The IEEE has created an unintelligable mess in order
  1641. * to decipher which key is used for which message.
  1642. *
  1643. * Let's hope it's simpler to implement for dissecting only.
  1644. *
  1645. * Also need to find the extended address of the sender.
  1646. */
  1647. if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
  1648. /* The source EUI-64 is included in the headers. */
  1649. srcAddr = packet->src64;
  1650. }
  1651. else if (ieee_hints && ieee_hints->map_rec && ieee_hints->map_rec->addr64) {
  1652. /* Use the hint */
  1653. srcAddr = ieee_hints->map_rec->addr64;
  1654. }
  1655. else {
  1656. /* Lookup failed. */
  1657. *status = DECRYPT_PACKET_NO_EXT_SRC_ADDR;
  1658. return NULL;
  1659. }
  1660. /* Lookup the key. */
  1661. /*
  1662. * TODO: What this dissector really needs is a UAT to store multiple keys
  1663. * and a variety of key configuration data. However, a single shared key
  1664. * should be sufficient to get packet encryption off to a start.
  1665. */
  1666. if (!ieee802154_key_valid) {
  1667. *status = DECRYPT_PACKET_NO_KEY;
  1668. return NULL;
  1669. }
  1670. memcpy(key, ieee802154_key, IEEE802154_CIPHER_SIZE);
  1671. /*=====================================================
  1672. * CCM* - CTR mode payload encryption
  1673. *=====================================================
  1674. */
  1675. /* Create the CCM* initial block for decryption (Adata=0, M=0, counter=0). */
  1676. ccm_init_block(tmp, FALSE, 0, srcAddr, packet, 0);
  1677. /* Decrypt the ciphertext, and place the plaintext in a new tvb. */
  1678. if (IEEE802154_IS_ENCRYPTED(packet->security_level) && captured_len) {
  1679. guint8 * text;
  1680. /*
  1681. * Make a copy of the ciphertext in heap memory.
  1682. *
  1683. * We will decrypt the message in-place and then use the buffer as the
  1684. * real data for the new tvb.
  1685. */
  1686. text = (guint8 *)tvb_memdup(tvb, offset, captured_len);
  1687. /* Perform CTR-mode transformation. */
  1688. if (!ccm_ctr_encrypt(key, tmp, rx_mic, text, captured_len)) {
  1689. g_free(text);
  1690. *status = DECRYPT_PACKET_DECRYPT_FAILED;
  1691. return NULL;
  1692. }
  1693. /* Create a tvbuff for the plaintext. */
  1694. ptext_tvb = tvb_new_child_real_data(tvb, text, captured_len, reported_len);
  1695. tvb_set_free_cb(ptext_tvb, g_free);
  1696. add_new_data_source(pinfo, ptext_tvb, "Decrypted IEEE 802.15.4 payload");
  1697. *status = DECRYPT_PACKET_SUCCEEDED;
  1698. }
  1699. /* There is no ciphertext. Wrap the plaintext in a new tvb. */
  1700. else {
  1701. /* Decrypt the MIC (if present). */
  1702. if ((have_mic) && (!ccm_ctr_encrypt(key, tmp, rx_mic, NULL, 0))) {
  1703. *status = DECRYPT_PACKET_DECRYPT_FAILED;
  1704. return NULL;
  1705. }
  1706. /* Create a tvbuff for the plaintext. This might result in a zero-length tvbuff. */
  1707. ptext_tvb = tvb_new_subset(tvb, offset, captured_len, reported_len);
  1708. *status = DECRYPT_PACKET_SUCCEEDED;
  1709. }
  1710. /*=====================================================
  1711. * CCM* - CBC-mode message authentication
  1712. *=====================================================
  1713. */
  1714. /* We can only verify the message if the MIC wasn't truncated. */
  1715. if (have_mic) {
  1716. unsigned char dec_mic[16];
  1717. guint l_m = captured_len;
  1718. guint l_a = offset;
  1719. /* Adjust the lengths of the plantext and additional data if unencrypted. */
  1720. if (!IEEE802154_IS_ENCRYPTED(packet->security_level)) {
  1721. l_a += l_m;
  1722. l_m = 0;
  1723. }
  1724. else if ((packet->version == IEEE802154_VERSION_2003) && !ieee802154_extend_auth)
  1725. l_a -= 5; /* Exclude Frame Counter (4 bytes) and Key Sequence Counter (1 byte) from authentication data */
  1726. /* Create the CCM* initial block for authentication (Adata!=0, M!=0, counter=l(m)). */
  1727. ccm_init_block(tmp, TRUE, M, srcAddr, packet, l_m);
  1728. /* Compute CBC-MAC authentication tag. */
  1729. /*
  1730. * And yes, despite the warning in tvbuff.h, I think tvb_get_ptr is the
  1731. * right function here since either A) the payload wasn't encrypted, in
  1732. * which case l_m is zero, or B) the payload was encrypted, and the tvb
  1733. * already points to contiguous memory, since we just allocated it in
  1734. * decryption phase.
  1735. */
  1736. if (!ccm_cbc_mac(key, tmp, (const gchar *)ep_tvb_memdup(tvb, 0, l_a), l_a, tvb_get_ptr(ptext_tvb, 0, l_m), l_m, dec_mic)) {
  1737. *status = DECRYPT_PACKET_MIC_CHECK_FAILED;
  1738. }
  1739. /* Compare the received MIC with the one we generated. */
  1740. else if (memcmp(rx_mic, dec_mic, M) != 0) {
  1741. *status = DECRYPT_PACKET_MIC_CHECK_FAILED;
  1742. }
  1743. }
  1744. /* Done! */
  1745. return ptext_tvb;
  1746. } /* dissect_ieee802154_decrypt */
  1747. /*FUNCTION:------------------------------------------------------
  1748. * NAME
  1749. * ccm_init_block
  1750. * DESCRIPTION
  1751. * Creates the CCM* initial block value for IEEE 802.15.4.
  1752. * PARAMETERS
  1753. * gchar *block - Output pointer for the initial block.
  1754. * gboolean adata - TRUE if additional auth data is present
  1755. * gint M - CCM* parameter M.
  1756. * guint64 addr - Source extended address.
  1757. * ieee802154_packet *packet - IEEE 802.15.4 packet information.
  1758. * guint16 ctr_val - Value in the last L bytes of the block.
  1759. * RETURNS
  1760. * void
  1761. *---------------------------------------------------------------
  1762. */
  1763. static void
  1764. ccm_init_block(gchar *block, gboolean adata, gint M, guint64 addr, ieee802154_packet * packet, gint ctr_val)
  1765. {
  1766. gint i = 0;
  1767. /* Flags: Reserved(0) || Adata || (M-2)/2 || (L-1) */
  1768. block[i] = (0x2 - 1); /* (L-1) */
  1769. if (M > 0) block[i] |= (((M-2)/2) << 3); /* (M-2)/2 */
  1770. if (adata) block[i] |= (1 << 6); /* Adata */
  1771. i++;
  1772. /* 2003 CCM Nonce: Source Address || Frame Counter || Key Sequence Counter */
  1773. /* 2006 CCM* Nonce: Source Address || Frame Counter || Security Level */
  1774. block[i++] = (guint8)((addr >> 56) & 0xff);
  1775. block[i++] = (guint8)((addr >> 48) & 0xff);
  1776. block[i++] = (guint8)((addr >> 40) & 0xff);
  1777. block[i++] = (guint8)((addr >> 32) & 0xff);
  1778. block[i++] = (guint8)((addr >> 24) & 0xff);
  1779. block[i++] = (guint8)((addr >> 16) & 0xff);
  1780. block[i++] = (guint8)((addr >> 8) & 0xff);
  1781. block[i++] = (guint8)((addr >> 0) & 0xff);
  1782. block[i++] = (guint8)((packet->frame_counter >> 24) & 0xff);
  1783. block[i++] = (guint8)((packet->frame_counter >> 16) & 0xff);
  1784. block[i++] = (guint8)((packet->frame_counter >> 8) & 0xff);
  1785. block[i++] = (guint8)((packet->frame_counter >> 0) & 0xff);
  1786. if (packet->version == IEEE802154_VERSION_2003)
  1787. block[i++] = packet->key_sequence_counter;
  1788. else
  1789. block[i++] = packet->security_level;
  1790. /* Plaintext length. */
  1791. block[i++] = (guint8)((ctr_val >> 8) & 0xff);
  1792. block[i] = (guint8)((ctr_val >> 0) & 0xff);
  1793. } /* ccm_init_block */
  1794. /*FUNCTION:------------------------------------------------------
  1795. * NAME
  1796. * ccm_ctr_encrypt
  1797. * DESCRIPTION
  1798. * Performs an in-place CTR-mode encryption/decryption.
  1799. * PARAMETERS
  1800. * const gchar *key - Encryption Key.
  1801. * const gchar *iv - Counter initial value.
  1802. * gchar *mic - MIC to encrypt/decrypt.
  1803. * gchar *data - Buffer to encrypt/decrypt.
  1804. * gint length - Length of the buffer.
  1805. * RETURNS
  1806. * gboolean - TRUE on SUCCESS, FALSE on error.
  1807. *---------------------------------------------------------------
  1808. */
  1809. static gboolean
  1810. ccm_ctr_encrypt(const gchar *key _U_, const gchar *iv _U_, gchar *mic _U_, gchar *data _U_, gint length _U_)
  1811. {
  1812. #ifdef HAVE_LIBGCRYPT
  1813. gcry_cipher_hd_t cipher_hd;
  1814. /* Open the cipher. */
  1815. if (gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR, 0)) {
  1816. return FALSE;
  1817. }
  1818. /* Set the key and initial value. */
  1819. if (gcry_cipher_setkey(cipher_hd, key, 16)) {
  1820. gcry_cipher_close(cipher_hd);
  1821. return FALSE;
  1822. }
  1823. if (gcry_cipher_setctr(cipher_hd, iv, 16)) {
  1824. gcry_cipher_close(cipher_hd);
  1825. return FALSE;
  1826. }
  1827. /* Decrypt the MIC. */
  1828. if (gcry_cipher_encrypt(cipher_hd, mic, 16, NULL, 0)) {
  1829. gcry_cipher_close(cipher_hd);
  1830. return FALSE;
  1831. }
  1832. /* Decrypt the payload. */
  1833. if (gcry_cipher_encrypt(cipher_hd, data, length, NULL, 0)) {
  1834. gcry_cipher_close(cipher_hd);
  1835. return FALSE;
  1836. }
  1837. /* Done with the cipher. */
  1838. gcry_cipher_close(cipher_hd);
  1839. return TRUE;
  1840. #else
  1841. return FALSE;
  1842. #endif
  1843. } /* ccm_ctr_encrypt */
  1844. /*FUNCTION:------------------------------------------------------
  1845. * NAME
  1846. * ccm_cbc_mac
  1847. * DESCRIPTION
  1848. * Generates a CBC-MAC of the decrypted payload and additional
  1849. * authentication headers.
  1850. * PARAMETERS
  1851. * const gchar key - Encryption Key.
  1852. * const gchar iv - Counter initial value.
  1853. * const gchar a - Additional auth headers.
  1854. * gint a_len - Length of the additional headers.
  1855. * const gchar m - Plaintext message.
  1856. * gint m_len - Length of plaintext message.
  1857. * gchar *mic - Output for CBC-MAC.
  1858. * RETURNS
  1859. * gboolean - TRUE on SUCCESS, FALSE on error.
  1860. *---------------------------------------------------------------
  1861. */
  1862. static gboolean
  1863. ccm_cbc_mac(const gchar *key _U_, const gchar *iv _U_, const gchar *a _U_, gint a_len _U_, const gchar *m _U_, gint m_len _U_, gchar *mic _U_)
  1864. {
  1865. #ifdef HAVE_LIBGCRYPT
  1866. gcry_cipher_hd_t cipher_hd;
  1867. guint i = 0;
  1868. unsigned char block[16];
  1869. /* Open the cipher. */
  1870. if (gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC, GCRY_CIPHER_CBC_MAC)) return FALSE;
  1871. /* Set the key. */
  1872. if (gcry_cipher_setkey(cipher_hd, key, 16)) {
  1873. gcry_cipher_close(cipher_hd);
  1874. return FALSE;
  1875. }
  1876. /* Process the initial value. */
  1877. if (gcry_cipher_encrypt(cipher_hd, mic, 16, iv, 16)) {
  1878. gcry_cipher_close(cipher_hd);
  1879. return FALSE;
  1880. }
  1881. /* Encode L(a) */
  1882. i = 0;
  1883. #if (GINT_MAX >= (1LL << 32))
  1884. if (a_len >= (1LL << 32)) {
  1885. block[i++] = 0xff;
  1886. block[i++] = 0xff;
  1887. block[i++] = (a_len >> 56) & 0xff;
  1888. block[i++] = (a_len >> 48) & 0xff;
  1889. block[i++] = (a_len >> 40) & 0xff;
  1890. block[i++] = (a_len >> 32) & 0xff;
  1891. block[i++] = (a_len >> 24) & 0xff;
  1892. block[i++] = (a_len >> 16) & 0xff;
  1893. block[i++] = (a_len >> 8) & 0xff;
  1894. block[i++] = (a_len >> 0) & 0xff;
  1895. }
  1896. else
  1897. #endif
  1898. if (a_len >= ((1 << 16) - (1 << 8))) {
  1899. block[i++] = 0xff;
  1900. block[i++] = 0xfe;
  1901. block[i++] = (a_len >> 24) & 0xff;
  1902. block[i++] = (a_len >> 16) & 0xff;
  1903. block[i++] = (a_len >> 8) & 0xff;
  1904. block[i++] = (a_len >> 0) & 0xff;
  1905. }
  1906. else {
  1907. block[i++] = (a_len >> 8) & 0xff;
  1908. block[i++] = (a_len >> 0) & 0xff;
  1909. }
  1910. /* Append a to get the first block of input (pad if we encounter the end of a). */
  1911. while ((i < sizeof(block)) && (a_len-- > 0)) block[i++] = *a++;
  1912. while (i < sizeof(block)) block[i++] = 0;
  1913. /* Process the first block of AuthData. */
  1914. if (gcry_cipher_encrypt(cipher_hd, mic, 16, block, 16)) {
  1915. gcry_cipher_close(cipher_hd);
  1916. return FALSE;
  1917. }
  1918. /* Transform and process the remainder of a. */
  1919. while (a_len > 0) {
  1920. /* Copy and pad. */
  1921. if ((guint)a_len >= sizeof(block)) memcpy(block, a, sizeof(block));
  1922. else {memcpy(block, a, a_len); memset(block+a_len, 0, sizeof(block)-a_len);}
  1923. /* Adjust pointers. */
  1924. a += sizeof(block);
  1925. a_len -= (int)sizeof(block);
  1926. /* Execute the CBC-MAC algorithm. */
  1927. if (gcry_cipher_encrypt(cipher_hd, mic, 16, block, sizeof(block))) {
  1928. gcry_cipher_close(cipher_hd);
  1929. return FALSE;
  1930. }
  1931. } /* while */
  1932. /* Process the message, m. */
  1933. while (m_len > 0) {
  1934. /* Copy and pad. */
  1935. if ((guint)m_len >= sizeof(block)) memcpy(block, m, sizeof(block));
  1936. else {memcpy(block, m, m_len); memset(block+m_len, 0, sizeof(block)-m_len);}
  1937. /* Adjust pointers. */
  1938. m += sizeof(block);
  1939. m_len -= (int)sizeof(block);
  1940. /* Execute the CBC-MAC algorithm. */
  1941. if (gcry_cipher_encrypt(cipher_hd, mic, 16, block, sizeof(block))) {
  1942. gcry_cipher_close(cipher_hd);
  1943. return FALSE;
  1944. }
  1945. }
  1946. /* Done with the cipher. */
  1947. gcry_cipher_close(cipher_hd);
  1948. return TRUE;
  1949. #else
  1950. return FALSE;
  1951. #endif
  1952. } /* ccm_cbc_mac */
  1953. /* Key hash function. */
  1954. guint ieee802154_short_addr_hash(gconstpointer key)
  1955. {
  1956. return (((ieee802154_short_addr *)key)->addr) | (((ieee802154_short_addr *)key)->pan << 16);
  1957. }
  1958. /* Key equal function. */
  1959. gboolean ieee802154_short_addr_equal(gconstpointer a, gconstpointer b)
  1960. {
  1961. return (((ieee802154_short_addr *)a)->pan == ((ieee802154_short_addr *)b)->pan) &&
  1962. (((ieee802154_short_addr *)a)->addr == ((ieee802154_short_addr *)b)->addr);
  1963. }
  1964. /* Key hash function. */
  1965. guint ieee802154_long_addr_hash(gconstpointer key)
  1966. {
  1967. return (guint)(((ieee802154_long_addr *)key)->addr) & 0xFFFFFFFF;
  1968. }
  1969. /* Key equal function. */
  1970. gboolean ieee802154_long_addr_equal(gconstpointer a, gconstpointer b)
  1971. {
  1972. return (((ieee802154_long_addr *)a)->addr == ((ieee802154_long_addr *)b)->addr);
  1973. }
  1974. /*FUNCTION:------------------------------------------------------
  1975. * NAME
  1976. * ieee802154_addr_update
  1977. * DESCRIPTION
  1978. * Creates a record that maps the given short address and pan
  1979. * to a long (extended) address.
  1980. * PARAMETERS
  1981. * guint16 short_addr - 16-bit short address
  1982. * guint16 pan - 16-bit PAN id
  1983. * guint64 long_addr - 64-bit long (extended) address
  1984. * const char * - Pointer to name of current protocol
  1985. * guint - Frame number this mapping became valid
  1986. * RETURNS
  1987. * TRUE - Record was updated
  1988. * FALSE - Couldn't find it
  1989. *---------------------------------------------------------------
  1990. */
  1991. ieee802154_map_rec *ieee802154_addr_update(ieee802154_map_tab_t *au_ieee802154_map,
  1992. guint16 short_addr, guint16 pan, guint64 long_addr, const char *proto, guint fnum)
  1993. {
  1994. ieee802154_short_addr addr16;
  1995. ieee802154_map_rec *p_map_rec;
  1996. gpointer old_key;
  1997. /* Look up short address hash */
  1998. addr16.pan = pan;
  1999. addr16.addr = short_addr;
  2000. p_map_rec = (ieee802154_map_rec *)g_hash_table_lookup(au_ieee802154_map->short_table, &addr16);
  2001. /* Update mapping record */
  2002. if (p_map_rec) {
  2003. /* record already exists */
  2004. if ( p_map_rec->addr64 == long_addr ) {
  2005. /* no change */
  2006. return p_map_rec;
  2007. }
  2008. else {
  2009. /* mark current mapping record invalid */
  2010. p_map_rec->end_fnum = fnum;
  2011. }
  2012. }
  2013. /* create a new mapping record */
  2014. p_map_rec = se_new(ieee802154_map_rec);
  2015. p_map_rec->proto = proto;
  2016. p_map_rec->start_fnum = fnum;
  2017. p_map_rec->end_fnum = 0;
  2018. p_map_rec->addr64 = long_addr;
  2019. /* link new mapping record to addr hash tables */
  2020. if ( g_hash_table_lookup_extended(au_ieee802154_map->short_table, &addr16, &old_key, NULL) ) {
  2021. /* update short addr hash table, reusing pointer to old key */
  2022. g_hash_table_insert(au_ieee802154_map->short_table, &old_key, p_map_rec);
  2023. } else {
  2024. /* create new hash entry */
  2025. g_hash_table_insert(au_ieee802154_map->short_table, se_memdup(&addr16, sizeof(addr16)), p_map_rec);
  2026. }
  2027. if ( g_hash_table_lookup_extended(au_ieee802154_map->long_table, &long_addr, &old_key, NULL) ) {
  2028. /* update long addr hash table, reusing pointer to old key */
  2029. g_hash_table_insert(au_ieee802154_map->long_table, &old_key, p_map_rec);
  2030. } else {
  2031. /* create new hash entry */
  2032. g_hash_table_insert(au_ieee802154_map->long_table, se_memdup(&long_addr, sizeof(long_addr)), p_map_rec);
  2033. }
  2034. return p_map_rec;
  2035. } /* ieee802154_addr_update */
  2036. /*FUNCTION:------------------------------------------------------
  2037. * NAME
  2038. * ieee802154_short_addr_invalidate
  2039. * DESCRIPTION
  2040. * Marks a mapping record associated with device with short_addr
  2041. * as invalid at a certain frame number, typically when a
  2042. * dissassociation occurs.
  2043. * PARAMETERS
  2044. * guint16 short_addr - 16-bit short address
  2045. * guint16 pan - 16-bit PAN id
  2046. * guint - Frame number when mapping became invalid
  2047. * RETURNS
  2048. * TRUE - Record was updated
  2049. * FALSE - Couldn't find it
  2050. *---------------------------------------------------------------
  2051. */
  2052. gboolean ieee802154_short_addr_invalidate(guint16 short_addr, guint16 pan, guint fnum)
  2053. {
  2054. ieee802154_short_addr addr16;
  2055. ieee802154_map_rec *map_rec;
  2056. addr16.pan = pan;
  2057. addr16.addr = short_addr;
  2058. map_rec = (ieee802154_map_rec *)g_hash_table_lookup(ieee802154_map.short_table, &addr16);
  2059. if ( map_rec ) {
  2060. /* indicates this mapping is invalid at frame fnum */
  2061. map_rec->end_fnum = fnum;
  2062. return TRUE;
  2063. }
  2064. return FALSE;
  2065. } /* ieee802154_short_addr_invalidate */
  2066. /*FUNCTION:------------------------------------------------------
  2067. * NAME
  2068. * ieee802154_long_addr_invalidate
  2069. * DESCRIPTION
  2070. * Marks a mapping record associated with device with long_addr
  2071. * as invalid at a certain frame number, typically when a
  2072. * dissassociation occurs.
  2073. * PARAMETERS
  2074. * guint64 long_addr - 16-bit short address
  2075. * guint - Frame number when mapping became invalid
  2076. * RETURNS
  2077. * TRUE - If record was updated
  2078. * FALSE - If record wasn't updated
  2079. *---------------------------------------------------------------
  2080. */
  2081. gboolean ieee802154_long_addr_invalidate(guint64 long_addr, guint fnum)
  2082. {
  2083. ieee802154_map_rec *map_rec;
  2084. map_rec = (ieee802154_map_rec *)g_hash_table_lookup(ieee802154_map.long_table, &long_addr);
  2085. if ( map_rec ) {
  2086. /* indicates this mapping is invalid at frame fnum */
  2087. map_rec->end_fnum = fnum;
  2088. return TRUE;
  2089. }
  2090. return FALSE;
  2091. } /* ieee802154_long_addr_invalidate */
  2092. /*FUNCTION:------------------------------------------------------
  2093. * NAME
  2094. * proto_init_ieee802154
  2095. * DESCRIPTION
  2096. * Init routine for the IEEE 802.15.4 dissector. Creates hash
  2097. * tables for mapping between 16-bit to 64-bit addresses and
  2098. * populates them with static address pairs from a UAT
  2099. * preference table.
  2100. * PARAMETERS
  2101. * none
  2102. * RETURNS
  2103. * void
  2104. *---------------------------------------------------------------
  2105. */
  2106. static void
  2107. proto_init_ieee802154(void)
  2108. {
  2109. guint i;
  2110. /* Destroy hash tables, if they exist. */
  2111. if (ieee802154_map.short_table)
  2112. g_hash_table_destroy(ieee802154_map.short_table);
  2113. if (ieee802154_map.long_table)
  2114. g_hash_table_destroy(ieee802154_map.long_table);
  2115. /* Create the hash tables. */
  2116. ieee802154_map.short_table = g_hash_table_new(ieee802154_short_addr_hash, ieee802154_short_addr_equal);
  2117. ieee802154_map.long_table = g_hash_table_new(ieee802154_long_addr_hash, ieee802154_long_addr_equal);
  2118. /* Re-load the hash table from the static address UAT. */
  2119. for (i=0; (i<num_static_addrs) && (static_addrs); i++) {
  2120. ieee802154_addr_update(&ieee802154_map,(guint16)static_addrs[i].addr16, (guint16)static_addrs[i].pan,
  2121. pntoh64(static_addrs[i].eui64), ieee802154_user, IEEE802154_USER_MAPPING);
  2122. } /* for */
  2123. } /* proto_init_ieee802154 */
  2124. /*FUNCTION:------------------------------------------------------
  2125. * NAME
  2126. * proto_register_ieee802154
  2127. * DESCRIPTION
  2128. * IEEE 802.15.4 protocol registration routine.
  2129. * PARAMETERS
  2130. * none
  2131. * RETURNS
  2132. * void
  2133. *---------------------------------------------------------------
  2134. */
  2135. void proto_register_ieee802154(void)
  2136. {
  2137. /* Protocol fields */
  2138. static hf_register_info hf_phy[] = {
  2139. /* PHY level */
  2140. { &hf_ieee802154_nonask_phy_preamble,
  2141. { "Preamble", "wpan-nonask-phy.preamble", FT_UINT32, BASE_HEX, NULL, 0x0,
  2142. NULL, HFILL }},
  2143. { &hf_ieee802154_nonask_phy_sfd,
  2144. { "Start of Frame Delimiter", "wpan-nonask-phy.sfd", FT_UINT8, BASE_HEX, NULL, 0x0,
  2145. NULL, HFILL }},
  2146. { &hf_ieee802154_nonask_phy_length,
  2147. { "Frame Length", "wpan-nonask-phy.frame_length", FT_UINT8, BASE_HEX, NULL,
  2148. IEEE802154_PHY_LENGTH_MASK, NULL, HFILL }},
  2149. };
  2150. static hf_register_info hf[] = {
  2151. { &hf_ieee802154_frame_length,
  2152. { "Frame Length", "wpan.frame_length", FT_UINT8, BASE_DEC, NULL, 0x0,
  2153. "Frame Length as reported from lower layer", HFILL }},
  2154. { &hf_ieee802154_frame_type,
  2155. { "Frame Type", "wpan.frame_type", FT_UINT16, BASE_HEX, VALS(ieee802154_frame_types),
  2156. IEEE802154_FCF_TYPE_MASK, NULL, HFILL }},
  2157. { &hf_ieee802154_security,
  2158. { "Security Enabled", "wpan.security", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_SEC_EN,
  2159. "Whether security operations are performed at the MAC layer or not.", HFILL }},
  2160. { &hf_ieee802154_pending,
  2161. { "Frame Pending", "wpan.pending", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_FRAME_PND,
  2162. "Indication of additional packets waiting to be transferred from the source device.", HFILL }},
  2163. { &hf_ieee802154_ack_request,
  2164. { "Acknowledge Request", "wpan.ack_request", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_ACK_REQ,
  2165. "Whether the sender of this packet requests acknowledgement or not.", HFILL }},
  2166. { &hf_ieee802154_intra_pan,
  2167. { "Intra-PAN", "wpan.intra_pan", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_INTRA_PAN,
  2168. "Whether this packet originated and terminated within the same PAN or not.", HFILL }},
  2169. { &hf_ieee802154_seqno,
  2170. { "Sequence Number", "wpan.seq_no", FT_UINT8, BASE_DEC, NULL, 0x0,
  2171. NULL, HFILL }},
  2172. { &hf_ieee802154_dst_addr_mode,
  2173. { "Destination Addressing Mode", "wpan.dst_addr_mode", FT_UINT16, BASE_HEX, VALS(ieee802154_addr_modes),
  2174. IEEE802154_FCF_DADDR_MASK, NULL, HFILL }},
  2175. { &hf_ieee802154_src_addr_mode,
  2176. { "Source Addressing Mode", "wpan.src_addr_mode", FT_UINT16, BASE_HEX, VALS(ieee802154_addr_modes),
  2177. IEEE802154_FCF_SADDR_MASK, NULL, HFILL }},
  2178. { &hf_ieee802154_version,
  2179. { "Frame Version", "wpan.version", FT_UINT16, BASE_DEC, NULL, IEEE802154_FCF_VERSION,
  2180. NULL, HFILL }},
  2181. { &hf_ieee802154_dst_panID,
  2182. { "Destination PAN", "wpan.dst_pan", FT_UINT16, BASE_HEX, NULL, 0x0,
  2183. NULL, HFILL }},
  2184. { &hf_ieee802154_dst16,
  2185. { "Destination", "wpan.dst16", FT_UINT16, BASE_HEX, NULL, 0x0,
  2186. NULL, HFILL }},
  2187. { &hf_ieee802154_dst64,
  2188. { "Destination", "wpan.dst64", FT_EUI64, BASE_NONE, NULL, 0x0,
  2189. NULL, HFILL }},
  2190. { &hf_ieee802154_src_panID,
  2191. { "Source PAN", "wpan.src_pan", FT_UINT16, BASE_HEX, NULL, 0x0,
  2192. NULL, HFILL }},
  2193. { &hf_ieee802154_src16,
  2194. { "Source", "wpan.src16", FT_UINT16, BASE_HEX, NULL, 0x0,
  2195. NULL, HFILL }},
  2196. { &hf_ieee802154_src64,
  2197. { "Extended Source", "wpan.src64", FT_EUI64, BASE_NONE, NULL, 0x0,
  2198. NULL, HFILL }},
  2199. { &hf_ieee802154_src64_origin,
  2200. { "Origin", "wpan.src64.origin", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
  2201. NULL, HFILL }},
  2202. { &hf_ieee802154_fcs,
  2203. { "FCS", "wpan.fcs", FT_UINT16, BASE_HEX, NULL, 0x0,
  2204. NULL, HFILL }},
  2205. { &hf_ieee802154_rssi,
  2206. { "RSSI", "wpan.rssi", FT_INT8, BASE_DEC, NULL, 0x0,
  2207. "Received Signal Strength", HFILL }},
  2208. { &hf_ieee802154_fcs_ok,
  2209. { "FCS Valid", "wpan.fcs_ok", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
  2210. NULL, HFILL }},
  2211. { &hf_ieee802154_correlation,
  2212. { "LQI Correlation Value", "wpan.correlation", FT_UINT8, BASE_DEC, NULL, 0x0,
  2213. NULL, HFILL }},
  2214. /* Command Frame Specific Fields */
  2215. /*--------------------------------*/
  2216. { &hf_ieee802154_cmd_id,
  2217. { "Command Identifier", "wpan.cmd", FT_UINT8, BASE_HEX, VALS(ieee802154_cmd_names), 0x0,
  2218. NULL, HFILL }},
  2219. /* Capability Information Fields */
  2220. { &hf_ieee802154_cinfo_alt_coord,
  2221. { "Alternate PAN Coordinator", "wpan.cinfo.alt_coord", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_ALT_PAN_COORD,
  2222. "Whether this device can act as a PAN coordinator or not.", HFILL }},
  2223. { &hf_ieee802154_cinfo_device_type,
  2224. { "Device Type", "wpan.cinfo.device_type", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_DEVICE_TYPE,
  2225. "Whether this device is RFD (reduced-function device) or FFD (full-function device).", HFILL }},
  2226. { &hf_ieee802154_cinfo_power_src,
  2227. { "Power Source", "wpan.cinfo.power_src", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_POWER_SRC,
  2228. "Whether this device is operating on AC/mains or battery power.", HFILL }},
  2229. { &hf_ieee802154_cinfo_idle_rx,
  2230. { "Receive On When Idle", "wpan.cinfo.idle_rx", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_IDLE_RX,
  2231. "Whether this device can receive packets while idle or not.", HFILL }},
  2232. { &hf_ieee802154_cinfo_sec_capable,
  2233. { "Security Capability", "wpan.cinfo.sec_capable", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_SEC_CAPABLE,
  2234. "Whether this device is capable of receiving encrypted packets.", HFILL }},
  2235. { &hf_ieee802154_cinfo_alloc_addr,
  2236. { "Allocate Address", "wpan.cinfo.alloc_addr", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_ALLOC_ADDR,
  2237. "Whether this device wishes to use a 16-bit short address instead of its IEEE 802.15.4 64-bit long address.", HFILL }},
  2238. /* Association response fields */
  2239. { &hf_ieee802154_assoc_addr,
  2240. { "Short Address", "wpan.asoc.addr", FT_UINT16, BASE_HEX, NULL, 0x0,
  2241. "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 }},
  2242. { &hf_ieee802154_assoc_status,
  2243. { "Association Status", "wpan.assoc.status", FT_UINT8, BASE_HEX, NULL, 0x0,
  2244. NULL, HFILL }},
  2245. { &hf_ieee802154_disassoc_reason,
  2246. { "Disassociation Reason", "wpan.disassoc.reason", FT_UINT8, BASE_HEX, NULL, 0x0,
  2247. NULL, HFILL }},
  2248. /* Coordinator Realignment fields */
  2249. { &hf_ieee802154_realign_pan,
  2250. { "PAN ID", "wpan.realign.pan", FT_UINT16, BASE_HEX, NULL, 0x0,
  2251. "The PAN identifier the coordinator wishes to use for future communication.", HFILL }},
  2252. { &hf_ieee802154_realign_caddr,
  2253. { "Coordinator Short Address", "wpan.realign.addr", FT_UINT16, BASE_HEX, NULL, 0x0,
  2254. "The 16-bit address the coordinator wishes to use for future communication.", HFILL }},
  2255. { &hf_ieee802154_realign_channel,
  2256. { "Logical Channel", "wpan.realign.channel", FT_UINT8, BASE_DEC, NULL, 0x0,
  2257. "The logical channel the coordinator wishes to use for future communication.", HFILL }},
  2258. { &hf_ieee802154_realign_addr,
  2259. { "Short Address", "wpan.realign.addr", FT_UINT16, BASE_HEX, NULL, 0x0,
  2260. "A short-address that the orphaned device shall assume if applicable.", HFILL }},
  2261. { &hf_ieee802154_realign_channel_page,
  2262. { "Channel Page", "wpan.realign.channel_page", FT_UINT8, BASE_DEC, NULL, 0x0,
  2263. "The logical channel page the coordinator wishes to use for future communication.", HFILL }},
  2264. { &hf_ieee802154_gtsreq_len,
  2265. { "GTS Length", "wpan.gtsreq.length", FT_UINT8, BASE_DEC, NULL, IEEE802154_CMD_GTS_REQ_LEN,
  2266. "Number of superframe slots the device is requesting.", HFILL }},
  2267. { &hf_ieee802154_gtsreq_dir,
  2268. { "GTS Direction", "wpan.gtsreq.direction", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_GTS_REQ_DIR,
  2269. "The direction of traffic in the guaranteed timeslot.", HFILL }},
  2270. { &hf_ieee802154_gtsreq_type,
  2271. { "Characteristic Type", "wpan.gtsreq.type", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_GTS_REQ_TYPE,
  2272. "Whether this request is to allocate or deallocate a timeslot.", HFILL }},
  2273. /* Beacon Frame Specific Fields */
  2274. /*-------------------------------*/
  2275. { &hf_ieee802154_beacon_order,
  2276. { "Beacon Interval", "wpan.beacon_order", FT_UINT16, BASE_DEC, NULL, IEEE802154_BEACON_ORDER_MASK,
  2277. "Specifies the transmission interval of the beacons.", HFILL }},
  2278. { &hf_ieee802154_superframe_order,
  2279. { "Superframe Interval", "wpan.superframe_order", FT_UINT16, BASE_DEC, NULL,
  2280. IEEE802154_SUPERFRAME_ORDER_MASK,
  2281. "Specifies the length of time the coordinator will interact with the PAN.", HFILL }},
  2282. { &hf_ieee802154_cap,
  2283. { "Final CAP Slot", "wpan.cap", FT_UINT16, BASE_DEC, NULL, IEEE802154_SUPERFRAME_CAP_MASK,
  2284. "Specifies the final superframe slot used by the CAP.", HFILL }},
  2285. { &hf_ieee802154_superframe_battery_ext,
  2286. { "Battery Extension", "wpan.battery_ext", FT_BOOLEAN, 16, NULL, IEEE802154_BATT_EXTENSION_MASK,
  2287. "Whether transmissions may not extend past the length of the beacon frame.", HFILL }},
  2288. { &hf_ieee802154_superframe_coord,
  2289. { "PAN Coordinator", "wpan.bcn_coord", FT_BOOLEAN, 16, NULL, IEEE802154_SUPERFRAME_COORD_MASK,
  2290. "Whether this beacon frame is being transmitted by the PAN coordinator or not.", HFILL }},
  2291. { &hf_ieee802154_assoc_permit,
  2292. { "Association Permit", "wpan.assoc_permit", FT_BOOLEAN, 16, NULL, IEEE802154_ASSOC_PERMIT_MASK,
  2293. "Whether this PAN is accepting association requests or not.", HFILL }},
  2294. { &hf_ieee802154_gts_count,
  2295. { "GTS Descriptor Count", "wpan.gts.count", FT_UINT8, BASE_DEC, NULL, 0x0,
  2296. "The number of GTS descriptors present in this beacon frame.", HFILL }},
  2297. { &hf_ieee802154_gts_permit,
  2298. { "GTS Permit", "wpan.gts.permit", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
  2299. "Whether the PAN coordinator is accepting GTS requests or not.", HFILL }},
  2300. { &hf_ieee802154_gts_direction,
  2301. { "Direction", "wpan.gts.direction", FT_BOOLEAN, BASE_NONE, TFS(&ieee802154_gts_direction_tfs), 0x0,
  2302. "A flag defining the direction of the GTS Slot.", HFILL }},
  2303. { &hf_ieee802154_pending16,
  2304. { "Address", "wpan.pending16", FT_UINT16, BASE_HEX, NULL, 0x0,
  2305. "Device with pending data to receive.", HFILL }},
  2306. { &hf_ieee802154_pending64,
  2307. { "Address", "wpan.pending64", FT_EUI64, BASE_NONE, NULL, 0x0,
  2308. "Device with pending data to receive.", HFILL }},
  2309. /* Auxiliary Security Header Fields */
  2310. /*----------------------------------*/
  2311. { &hf_ieee802154_security_level,
  2312. { "Security Level", "wpan.aux_sec.sec_level", FT_UINT8, BASE_HEX, VALS(ieee802154_sec_level_names),
  2313. IEEE802154_AUX_SEC_LEVEL_MASK, "The Security Level of the frame", HFILL }},
  2314. { &hf_ieee802154_key_id_mode,
  2315. { "Key Identifier Mode", "wpan.aux_sec.key_id_mode", FT_UINT8, BASE_HEX, VALS(ieee802154_key_id_mode_names),
  2316. IEEE802154_AUX_KEY_ID_MODE_MASK,
  2317. "The scheme to use by the recipient to lookup the key in its key table", HFILL }},
  2318. { &hf_ieee802154_aux_sec_reserved,
  2319. { "Reserved", "wpan.aux_sec.reserved", FT_UINT8, BASE_HEX, NULL, IEEE802154_AUX_KEY_RESERVED_MASK,
  2320. NULL, HFILL }},
  2321. { &hf_ieee802154_aux_sec_frame_counter,
  2322. { "Frame Counter", "wpan.aux_sec.frame_counter", FT_UINT32, BASE_DEC, NULL, 0x0,
  2323. "Frame counter of the originator of the protected frame", HFILL }},
  2324. { &hf_ieee802154_aux_sec_key_source,
  2325. { "Key Source", "wpan.aux_sec.key_source", FT_UINT64, BASE_HEX, NULL, 0x0,
  2326. "Key Source for processing of the protected frame", HFILL }},
  2327. { &hf_ieee802154_aux_sec_key_index,
  2328. { "Key Index", "wpan.aux_sec.key_index", FT_UINT8, BASE_HEX, NULL, 0x0,
  2329. "Key Index for processing of the protected frame", HFILL }},
  2330. /* IEEE 802.15.4-2003 Security Header Fields */
  2331. { &hf_ieee802154_sec_frame_counter,
  2332. { "Frame Counter", "wpan.sec_frame_counter", FT_UINT32, BASE_HEX, NULL, 0x0,
  2333. "Frame counter of the originator of the protected frame (802.15.4-2003)", HFILL }},
  2334. { &hf_ieee802154_sec_key_sequence_counter,
  2335. { "Key Sequence Counter", "wpan.sec_key_sequence_counter", FT_UINT8, BASE_HEX, NULL, 0x0,
  2336. "Key Sequence counter of the originator of the protected frame (802.15.4-2003)", HFILL }}
  2337. };
  2338. /* Subtrees */
  2339. static gint *ett[] = {
  2340. &ett_ieee802154_nonask_phy,
  2341. &ett_ieee802154_nonask_phy_phr,
  2342. &ett_ieee802154,
  2343. &ett_ieee802154_fcf,
  2344. &ett_ieee802154_auxiliary_security,
  2345. &ett_ieee802154_aux_sec_control,
  2346. &ett_ieee802154_aux_sec_key_id,
  2347. &ett_ieee802154_fcs,
  2348. &ett_ieee802154_cmd,
  2349. &ett_ieee802154_superframe,
  2350. &ett_ieee802154_gts,
  2351. &ett_ieee802154_gts_direction,
  2352. &ett_ieee802154_gts_descriptors,
  2353. &ett_ieee802154_pendaddr
  2354. };
  2355. /* Preferences. */
  2356. module_t *ieee802154_module;
  2357. static uat_field_t addr_uat_flds[] = {
  2358. UAT_FLD_HEX(addr_uat,addr16,"Short Address",
  2359. "16-bit short address in hexadecimal."),
  2360. UAT_FLD_HEX(addr_uat,pan,"PAN Identifier",
  2361. "16-bit PAN identifier in hexadecimal."),
  2362. UAT_FLD_BUFFER(addr_uat,eui64,"EUI-64",
  2363. "64-bit extended unique identifier."),
  2364. UAT_END_FIELDS
  2365. };
  2366. /* Register the init routine. */
  2367. register_init_routine(proto_init_ieee802154);
  2368. /* Register Protocol name and description. */
  2369. proto_ieee802154 = proto_register_protocol("IEEE 802.15.4 Low-Rate Wireless PAN", "IEEE 802.15.4",
  2370. IEEE802154_PROTOABBREV_WPAN);
  2371. proto_ieee802154_nonask_phy = proto_register_protocol("IEEE 802.15.4 Low-Rate Wireless PAN non-ASK PHY",
  2372. "IEEE 802.15.4 non-ASK PHY", "wpan-nonask-phy");
  2373. /* Register header fields and subtrees. */
  2374. proto_register_field_array(proto_ieee802154, hf, array_length(hf));
  2375. proto_register_field_array(proto_ieee802154, hf_phy, array_length(hf_phy));
  2376. proto_register_subtree_array(ett, array_length(ett));
  2377. /* add a user preference to set the 802.15.4 ethertype */
  2378. ieee802154_module = prefs_register_protocol(proto_ieee802154,
  2379. proto_reg_handoff_ieee802154);
  2380. prefs_register_uint_preference(ieee802154_module, "802154_ethertype",
  2381. "802.15.4 Ethertype (in hex)",
  2382. "(Hexadecimal) Ethertype used to indicate IEEE 802.15.4 frame.",
  2383. 16, &ieee802154_ethertype);
  2384. prefs_register_bool_preference(ieee802154_module, "802154_cc24xx",
  2385. "TI CC24xx FCS format",
  2386. "Set if the FCS field is in TI CC24xx format.",
  2387. &ieee802154_cc24xx);
  2388. prefs_register_bool_preference(ieee802154_module, "802154_fcs_ok",
  2389. "Dissect only good FCS",
  2390. "Dissect payload only if FCS is valid.",
  2391. &ieee802154_fcs_ok);
  2392. /* Create a UAT for static address mappings. */
  2393. static_addr_uat = uat_new("Static Addresses",
  2394. sizeof(static_addr_t), /* record size */
  2395. "802154_addresses", /* filename */
  2396. TRUE, /* from_profile */
  2397. (void**)&static_addrs, /* data_ptr */
  2398. &num_static_addrs, /* numitems_ptr */
  2399. UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */
  2400. NULL, /* help */
  2401. NULL, /* copy callback */
  2402. addr_uat_update_cb, /* update callback */
  2403. NULL, /* free callback */
  2404. NULL, /* post update callback */
  2405. addr_uat_flds); /* UAT field definitions */
  2406. prefs_register_uat_preference(ieee802154_module, "static_addr",
  2407. "Static Addresses",
  2408. "A table of static address mappings between 16-bit short addressing and EUI-64 addresses",
  2409. static_addr_uat);
  2410. /* Register preferences for a decryption key */
  2411. /* TODO: Implement a UAT for multiple keys, and with more advanced key management. */
  2412. prefs_register_string_preference(ieee802154_module, "802154_key", "Decryption key",
  2413. "128-bit decryption key in hexadecimal format", (const char **)&ieee802154_key_str);
  2414. prefs_register_enum_preference(ieee802154_module, "802154_sec_suite",
  2415. "Security Suite (802.15.4-2003)",
  2416. "Specifies the security suite to use for 802.15.4-2003 secured frames"
  2417. " (only supported suites are listed). Option ignored for 802.15.4-2006"
  2418. " and unsecured frames.",
  2419. &ieee802154_sec_suite, ieee802154_2003_sec_suite_enums, FALSE);
  2420. prefs_register_bool_preference(ieee802154_module, "802154_extend_auth",
  2421. "Extend authentication data (802.15.4-2003)",
  2422. "Set if the manufacturer extends the authentication data with the"
  2423. " security header. Option ignored for 802.15.4-2006 and unsecured frames.",
  2424. &ieee802154_extend_auth);
  2425. /* Register the subdissector list */
  2426. register_heur_dissector_list(IEEE802154_PROTOABBREV_WPAN, &ieee802154_heur_subdissector_list);
  2427. /* Register dissectors with Wireshark. */
  2428. register_dissector(IEEE802154_PROTOABBREV_WPAN, dissect_ieee802154, proto_ieee802154);
  2429. register_dissector("wpan_nofcs", dissect_ieee802154_nofcs, proto_ieee802154);
  2430. register_dissector("wpan_cc24xx", dissect_ieee802154_cc24xx, proto_ieee802154);
  2431. register_dissector("wpan-nonask-phy", dissect_ieee802154_nonask_phy, proto_ieee802154_nonask_phy);
  2432. } /* proto_register_ieee802154 */
  2433. /*FUNCTION:------------------------------------------------------
  2434. * NAME
  2435. * proto_reg_handoff_ieee802154
  2436. * DESCRIPTION
  2437. * Registers the IEEE 802.15.4 dissector with Wireshark.
  2438. * Will be called every time 'apply' is pressed in the preferences menu.
  2439. * as well as during Wireshark initialization
  2440. * PARAMETERS
  2441. * none
  2442. * RETURNS
  2443. * void
  2444. *---------------------------------------------------------------
  2445. */
  2446. void proto_reg_handoff_ieee802154(void)
  2447. {
  2448. static gboolean prefs_initialized = FALSE;
  2449. static dissector_handle_t ieee802154_handle;
  2450. static dissector_handle_t ieee802154_nonask_phy_handle;
  2451. static dissector_handle_t ieee802154_nofcs_handle;
  2452. static unsigned int old_ieee802154_ethertype;
  2453. GByteArray *bytes;
  2454. gboolean res;
  2455. if (!prefs_initialized){
  2456. /* Get the dissector handles. */
  2457. ieee802154_handle = find_dissector(IEEE802154_PROTOABBREV_WPAN);
  2458. ieee802154_nonask_phy_handle = find_dissector("wpan-nonask-phy");
  2459. ieee802154_nofcs_handle = find_dissector("wpan_nofcs");
  2460. data_handle = find_dissector("data");
  2461. dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE802_15_4, ieee802154_handle);
  2462. dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE802_15_4_NONASK_PHY, ieee802154_nonask_phy_handle);
  2463. dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE802_15_4_NOFCS, ieee802154_nofcs_handle);
  2464. dissector_add_uint("sll.ltype", LINUX_SLL_P_IEEE802154, ieee802154_handle);
  2465. prefs_initialized = TRUE;
  2466. } else {
  2467. dissector_delete_uint("ethertype", old_ieee802154_ethertype, ieee802154_handle);
  2468. }
  2469. old_ieee802154_ethertype = ieee802154_ethertype;
  2470. /* Get the IEEE 802.15.4 decryption key. */
  2471. bytes = g_byte_array_new();
  2472. res = hex_str_to_bytes(ieee802154_key_str, bytes, FALSE);
  2473. ieee802154_key_valid = (res && bytes->len >= IEEE802154_CIPHER_SIZE);
  2474. if (ieee802154_key_valid) {
  2475. memcpy(ieee802154_key, bytes->data, IEEE802154_CIPHER_SIZE);
  2476. }
  2477. g_byte_array_free(bytes, TRUE);
  2478. /* Register dissector handles. */
  2479. dissector_add_uint("ethertype", ieee802154_ethertype, ieee802154_handle);
  2480. } /* proto_reg_handoff_ieee802154 */