1 /* 2 * Copyright (c) 2016 Intel Corporation. 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 /** 8 * @file 9 * @brief IEEE 802.15.4 MAC frame related functions 10 * 11 * @details This is not to be included by the application. 12 * 13 * @note All references to the standard in this file cite IEEE 802.15.4-2020. 14 * 15 * @note All structs and attributes (e.g. PAN id, ext address and short address) 16 * in this file that directly represent parts of IEEE 802.15.4 frames are in 17 * LITTLE ENDIAN, see section 4, especially section 4.3. 18 */ 19 20 #ifndef __IEEE802154_FRAME_H__ 21 #define __IEEE802154_FRAME_H__ 22 23 #include <zephyr/kernel.h> 24 #include <zephyr/net/ieee802154.h> 25 #include <zephyr/net/net_pkt.h> 26 #include <zephyr/toolchain.h> 27 28 #define IEEE802154_ACK_PKT_LENGTH 3 /* Imm-Ack length, see section 7.3.3 */ 29 #define IEEE802154_MIN_LENGTH IEEE802154_ACK_PKT_LENGTH 30 31 #define IEEE802154_FCF_SEQ_LENGTH 3 32 #define IEEE802154_PAN_ID_LENGTH 2 33 34 #define IEEE802154_BEACON_MIN_SIZE 4 35 #define IEEE802154_BEACON_SF_SIZE 2 36 #define IEEE802154_BEACON_GTS_SPEC_SIZE 1 37 #define IEEE802154_BEACON_GTS_IF_MIN_SIZE IEEE802154_BEACON_GTS_SPEC_SIZE 38 #define IEEE802154_BEACON_PAS_SPEC_SIZE 1 39 #define IEEE802154_BEACON_PAS_IF_MIN_SIZE IEEE802154_BEACON_PAS_SPEC_SIZE 40 #define IEEE802154_BEACON_GTS_DIR_SIZE 1 41 #define IEEE802154_BEACON_GTS_SIZE 3 42 #define IEEE802154_BEACON_GTS_RX 1 43 #define IEEE802154_BEACON_GTS_TX 0 44 45 /** see section 7.2.2.2 */ 46 enum ieee802154_frame_type { 47 IEEE802154_FRAME_TYPE_BEACON = 0x0, 48 IEEE802154_FRAME_TYPE_DATA = 0x1, 49 IEEE802154_FRAME_TYPE_ACK = 0x2, 50 IEEE802154_FRAME_TYPE_MAC_COMMAND = 0x3, 51 IEEE802154_FRAME_TYPE_RESERVED = 0x4, 52 IEEE802154_FRAME_TYPE_MULTIPURPOSE = 0x5, 53 IEEE802154_FRAME_TYPE_FRAK = 0x6, 54 IEEE802154_FRAME_TYPE_EXTENDED = 0x7, 55 }; 56 57 /** see section 7.2.2.9, table 7-3 */ 58 enum ieee802154_addressing_mode { 59 IEEE802154_ADDR_MODE_NONE = 0x0, 60 IEEE802154_ADDR_MODE_RESERVED = 0x1, 61 IEEE802154_ADDR_MODE_SHORT = 0x2, 62 IEEE802154_ADDR_MODE_EXTENDED = 0x3, 63 }; 64 65 /** see section 7.2.2.10 */ 66 enum ieee802154_version { 67 IEEE802154_VERSION_802154_2003 = 0x0, 68 IEEE802154_VERSION_802154_2006 = 0x1, 69 IEEE802154_VERSION_802154 = 0x2, 70 IEEE802154_VERSION_RESERVED = 0x3, 71 }; 72 73 /** Frame Control Field, see section 7.2.2 */ 74 struct ieee802154_fcf_seq { 75 struct { 76 #ifdef CONFIG_LITTLE_ENDIAN 77 uint16_t frame_type : 3; 78 uint16_t security_enabled : 1; 79 uint16_t frame_pending : 1; 80 uint16_t ar : 1; 81 uint16_t pan_id_comp : 1; 82 uint16_t reserved : 1; 83 uint16_t seq_num_suppr : 1; 84 uint16_t ie_list : 1; 85 uint16_t dst_addr_mode : 2; 86 uint16_t frame_version : 2; 87 uint16_t src_addr_mode : 2; 88 #else 89 uint16_t reserved : 1; 90 uint16_t pan_id_comp : 1; 91 uint16_t ar : 1; 92 uint16_t frame_pending : 1; 93 uint16_t security_enabled : 1; 94 uint16_t frame_type : 3; 95 uint16_t src_addr_mode : 2; 96 uint16_t frame_version : 2; 97 uint16_t dst_addr_mode : 2; 98 uint16_t ie_list : 1; 99 uint16_t seq_num_suppr : 1; 100 #endif 101 } fc __packed; 102 103 uint8_t sequence; 104 } __packed; 105 106 struct ieee802154_address { 107 union { 108 uint16_t short_addr; 109 uint8_t ext_addr[0]; 110 }; 111 } __packed; 112 113 struct ieee802154_address_field_comp { 114 struct ieee802154_address addr; 115 } __packed; 116 117 struct ieee802154_address_field_plain { 118 uint16_t pan_id; 119 struct ieee802154_address addr; 120 } __packed; 121 122 struct ieee802154_address_field { 123 union { 124 struct ieee802154_address_field_plain plain; 125 struct ieee802154_address_field_comp comp; 126 }; 127 } __packed; 128 129 /** see section 9.4.2.2, table 9-6 */ 130 enum ieee802154_security_level { 131 IEEE802154_SECURITY_LEVEL_NONE = 0x0, 132 IEEE802154_SECURITY_LEVEL_MIC_32 = 0x1, 133 IEEE802154_SECURITY_LEVEL_MIC_64 = 0x2, 134 IEEE802154_SECURITY_LEVEL_MIC_128 = 0x3, 135 IEEE802154_SECURITY_LEVEL_RESERVED = 0x4, 136 IEEE802154_SECURITY_LEVEL_ENC_MIC_32 = 0x5, 137 IEEE802154_SECURITY_LEVEL_ENC_MIC_64 = 0x6, 138 IEEE802154_SECURITY_LEVEL_ENC_MIC_128 = 0x7, 139 }; 140 141 /** Levels above this level will be encrypted. */ 142 #define IEEE802154_SECURITY_LEVEL_ENC IEEE802154_SECURITY_LEVEL_RESERVED 143 144 /** This will match above *_MIC_<32/64/128> */ 145 #define IEEE802154_AUTH_TAG_LENGTH_32 4 146 #define IEEE802154_AUTH_TAG_LENGTH_64 8 147 #define IEEE802154_AUTH_TAG_LENGTH_128 16 148 149 /** see section 9.4.2.3, table 9-7 */ 150 enum ieee802154_key_id_mode { 151 IEEE802154_KEY_ID_MODE_IMPLICIT = 0x0, 152 IEEE802154_KEY_ID_MODE_INDEX = 0x1, 153 IEEE802154_KEY_ID_MODE_SRC_4_INDEX = 0x2, 154 IEEE802154_KEY_ID_MODE_SRC_8_INDEX = 0x3, 155 }; 156 157 #define IEEE802154_KEY_ID_FIELD_INDEX_LENGTH 1 158 #define IEEE802154_KEY_ID_FIELD_SRC_4_INDEX_LENGTH 5 159 #define IEEE802154_KEY_ID_FIELD_SRC_8_INDEX_LENGTH 9 160 161 #define IEEE802154_KEY_MAX_LEN 16 162 163 /** see section 9.4.2 */ 164 struct ieee802154_security_control_field { 165 #ifdef CONFIG_LITTLE_ENDIAN 166 uint8_t security_level : 3; 167 uint8_t key_id_mode : 2; 168 uint8_t reserved : 3; 169 #else 170 uint8_t reserved : 3; 171 uint8_t key_id_mode : 2; 172 uint8_t security_level : 3; 173 #endif 174 } __packed; 175 176 #define IEEE802154_SECURITY_CF_LENGTH 1 177 178 /** 179 * @brief see section 9.4.4 180 * 181 * @note Currently only mode 0 is supported, so this structure holds no info, 182 * yet. 183 */ 184 struct ieee802154_key_identifier_field { 185 union { 186 struct { 187 uint8_t key_index; 188 } mode_1; 189 190 struct { 191 uint8_t key_src[4]; 192 uint8_t key_index; 193 } mode_2; 194 195 struct { 196 uint8_t key_src[8]; 197 uint8_t key_index; 198 } mode_3; 199 }; 200 } __packed; 201 202 /** Auxiliary Security Header, see section 9.4 */ 203 struct ieee802154_aux_security_hdr { 204 struct ieee802154_security_control_field control; 205 uint32_t frame_counter; 206 struct ieee802154_key_identifier_field kif; 207 } __packed; 208 209 #define IEEE802154_SECURITY_FRAME_COUNTER_LENGTH 4 210 211 /** MAC header and footer, see section 7.2.1 */ 212 struct ieee802154_mhr { 213 struct ieee802154_fcf_seq *fs; 214 struct ieee802154_address_field *dst_addr; 215 struct ieee802154_address_field *src_addr; 216 #ifdef CONFIG_NET_L2_IEEE802154_SECURITY 217 struct ieee802154_aux_security_hdr *aux_sec; 218 #endif 219 }; 220 221 /** see section 7.3.1.5, figure 7-10 */ 222 struct ieee802154_gts_dir { 223 #ifdef CONFIG_LITTLE_ENDIAN 224 uint8_t mask : 7; 225 uint8_t reserved : 1; 226 #else 227 uint8_t reserved : 1; 228 uint8_t mask : 7; 229 #endif 230 } __packed; 231 232 /** see section 7.3.1.5, figure 7-11 */ 233 struct ieee802154_gts { 234 uint16_t short_address; 235 #ifdef CONFIG_LITTLE_ENDIAN 236 uint8_t starting_slot : 4; 237 uint8_t length : 4; 238 #else 239 uint8_t length : 4; 240 uint8_t starting_slot : 4; 241 #endif 242 } __packed; 243 244 /** see section 7.3.1.5, figure 7-9 */ 245 struct ieee802154_gts_spec { 246 #ifdef CONFIG_LITTLE_ENDIAN 247 /* Descriptor Count */ 248 uint8_t desc_count : 3; 249 uint8_t reserved : 4; 250 /* GTS Permit */ 251 uint8_t permit : 1; 252 #else 253 /* GTS Permit */ 254 uint8_t permit : 1; 255 uint8_t reserved : 4; 256 /* Descriptor Count */ 257 uint8_t desc_count : 3; 258 #endif 259 } __packed; 260 261 /** see section 7.3.1.6, figure 7-13 */ 262 struct ieee802154_pas_spec { 263 #ifdef CONFIG_LITTLE_ENDIAN 264 /* Number of Short Addresses Pending */ 265 uint8_t nb_sap : 3; 266 uint8_t reserved_1 : 1; 267 /* Number of Extended Addresses Pending */ 268 uint8_t nb_eap : 3; 269 uint8_t reserved_2 : 1; 270 #else 271 uint8_t reserved_1 : 1; 272 /* Number of Extended Addresses Pending */ 273 uint8_t nb_eap : 3; 274 uint8_t reserved_2 : 1; 275 /* Number of Short Addresses Pending */ 276 uint8_t nb_sap : 3; 277 #endif 278 } __packed; 279 280 /** see section 7.3.1.4, figure 7-7 */ 281 struct ieee802154_beacon_sf { 282 #ifdef CONFIG_LITTLE_ENDIAN 283 /* Beacon Order*/ 284 uint16_t bc_order : 4; 285 /* Superframe Order*/ 286 uint16_t sf_order : 4; 287 /* Final CAP Slot */ 288 uint16_t cap_slot : 4; 289 /* Battery Life Extension */ 290 uint16_t ble : 1; 291 uint16_t reserved : 1; 292 /* PAN Coordinator */ 293 uint16_t coordinator : 1; 294 /* Association Permit */ 295 uint16_t association : 1; 296 #else 297 /* Superframe Order*/ 298 uint16_t sf_order : 4; 299 /* Beacon Order*/ 300 uint16_t bc_order : 4; 301 /* Association Permit */ 302 uint16_t association : 1; 303 /* PAN Coordinator */ 304 uint16_t coordinator : 1; 305 uint16_t reserved : 1; 306 /* Battery Life Extension */ 307 uint16_t ble : 1; 308 /* Final CAP Slot */ 309 uint16_t cap_slot : 4; 310 #endif 311 } __packed; 312 313 /** see section 7.3.1.1, figure 7-5 */ 314 struct ieee802154_beacon { 315 struct ieee802154_beacon_sf sf; 316 317 /* GTS Fields - Spec is always there */ 318 struct ieee802154_gts_spec gts; 319 } __packed; 320 321 /** See section 7.5.2 */ 322 struct ieee802154_cmd_assoc_req { 323 struct { 324 #ifdef CONFIG_LITTLE_ENDIAN 325 uint8_t reserved_1 : 1; 326 uint8_t dev_type : 1; 327 uint8_t power_src : 1; 328 uint8_t rx_on : 1; 329 uint8_t association_type : 1; 330 uint8_t reserved_2 : 1; 331 uint8_t sec_capability : 1; 332 uint8_t alloc_addr : 1; 333 #else 334 uint8_t alloc_addr : 1; 335 uint8_t sec_capability : 1; 336 uint8_t reserved_2 : 1; 337 uint8_t association_type : 1; 338 uint8_t rx_on : 1; 339 uint8_t power_src : 1; 340 uint8_t dev_type : 1; 341 uint8_t reserved_1 : 1; 342 #endif 343 } ci; 344 } __packed; 345 346 #define IEEE802154_CMD_ASSOC_REQ_LENGTH 1 347 348 /** see section 7.5.3 */ 349 enum ieee802154_association_status_field { 350 IEEE802154_ASF_SUCCESSFUL = 0x00, 351 IEEE802154_ASF_PAN_AT_CAPACITY = 0x01, 352 IEEE802154_ASF_PAN_ACCESS_DENIED = 0x02, 353 IEEE802154_ASF_RESERVED = 0x03, 354 IEEE802154_ASF_RESERVED_PRIMITIVES = 0x80, 355 }; 356 357 struct ieee802154_cmd_assoc_res { 358 uint16_t short_addr; 359 uint8_t status; 360 } __packed; 361 362 #define IEEE802154_CMD_ASSOC_RES_LENGTH 3 363 364 /** see section 7.5.4 */ 365 enum ieee802154_disassociation_reason_field { 366 IEEE802154_DRF_RESERVED_1 = 0x00, 367 IEEE802154_DRF_COORDINATOR_WISH = 0x01, 368 IEEE802154_DRF_DEVICE_WISH = 0x02, 369 IEEE802154_DRF_RESERVED_2 = 0x03, 370 IEEE802154_DRF_RESERVED_PRIMITIVES = 0x80, 371 }; 372 373 struct ieee802154_cmd_disassoc_note { 374 uint8_t reason; 375 } __packed; 376 377 #define IEEE802154_CMD_DISASSOC_NOTE_LENGTH 1 378 379 /** Coordinator realignment, see section 7.5.10 */ 380 struct ieee802154_cmd_coord_realign { 381 uint16_t pan_id; 382 uint16_t coordinator_short_addr; 383 uint8_t channel; 384 uint16_t short_addr; 385 uint8_t channel_page; /* optional */ 386 } __packed; 387 388 #define IEEE802154_CMD_COORD_REALIGN_LENGTH 3 389 390 /** GTS request, see section 7.5.11 */ 391 struct ieee802154_gts_request { 392 struct { 393 #ifdef CONFIG_LITTLE_ENDIAN 394 uint8_t length : 4; 395 uint8_t direction : 1; 396 uint8_t type : 1; 397 uint8_t reserved : 2; 398 #else 399 uint8_t reserved : 2; 400 uint8_t type : 1; 401 uint8_t direction : 1; 402 uint8_t length : 4; 403 #endif 404 } gts; 405 } __packed; 406 407 #define IEEE802154_GTS_REQUEST_LENGTH 1 408 409 /** Command Frame Identifiers (CFI), see section 7.5.1 */ 410 enum ieee802154_cfi { 411 IEEE802154_CFI_UNKNOWN = 0x00, 412 IEEE802154_CFI_ASSOCIATION_REQUEST = 0x01, 413 IEEE802154_CFI_ASSOCIATION_RESPONSE = 0x02, 414 IEEE802154_CFI_DISASSOCIATION_NOTIFICATION = 0x03, 415 IEEE802154_CFI_DATA_REQUEST = 0x04, 416 IEEE802154_CFI_PAN_ID_CONFLICT_NOTIFICATION = 0x05, 417 IEEE802154_CFI_ORPHAN_NOTIFICATION = 0x06, 418 IEEE802154_CFI_BEACON_REQUEST = 0x07, 419 IEEE802154_CFI_COORDINATOR_REALIGNEMENT = 0x08, 420 IEEE802154_CFI_GTS_REQUEST = 0x09, 421 IEEE802154_CFI_RESERVED = 0x0a, 422 }; 423 424 struct ieee802154_command { 425 uint8_t cfi; 426 union { 427 struct ieee802154_cmd_assoc_req assoc_req; 428 struct ieee802154_cmd_assoc_res assoc_res; 429 struct ieee802154_cmd_disassoc_note disassoc_note; 430 struct ieee802154_cmd_coord_realign coord_realign; 431 struct ieee802154_gts_request gts_request; 432 /* Data request, PAN ID conflict, orphan notification 433 * or beacon request just provide the CFI. 434 */ 435 }; 436 } __packed; 437 438 #define IEEE802154_CMD_CFI_LENGTH 1 439 440 /** Frame */ 441 struct ieee802154_mpdu { 442 struct ieee802154_mhr mhr; 443 union { 444 void *payload; 445 struct ieee802154_beacon *beacon; 446 struct ieee802154_command *command; 447 }; 448 uint16_t payload_length; 449 }; 450 451 /** Frame build parameters */ 452 struct ieee802154_frame_params { 453 struct { 454 union { 455 uint8_t ext_addr[IEEE802154_EXT_ADDR_LENGTH]; /* in big endian */ 456 uint16_t short_addr; /* in CPU byte order */ 457 }; 458 459 uint16_t len; 460 uint16_t pan_id; /* in CPU byte order */ 461 } dst; 462 463 uint16_t short_addr; /* in CPU byte order */ 464 uint16_t pan_id; /* in CPU byte order */ 465 } __packed; 466 467 #ifdef CONFIG_NET_L2_IEEE802154_SECURITY 468 struct ieee802154_aux_security_hdr * 469 ieee802154_validate_aux_security_hdr(uint8_t *buf, uint8_t **p_buf, uint8_t *length); 470 #endif 471 472 struct ieee802154_fcf_seq *ieee802154_validate_fc_seq(uint8_t *buf, uint8_t **p_buf, 473 uint8_t *length); 474 475 /** 476 * @brief Calculate the beacon header length. 477 * 478 * @details Returns the length of the MAC payload without the beacon payload, 479 * see section 7.3.1.1, figure 7-5. 480 * 481 * @param buf pointer to the MAC payload 482 * @param length buffer length 483 * 484 * @retval -EINVAL The header is invalid. 485 * @return the length of the beacon header 486 */ 487 int ieee802514_beacon_header_length(uint8_t *buf, uint8_t length); 488 489 bool ieee802154_validate_frame(uint8_t *buf, uint8_t length, struct ieee802154_mpdu *mpdu); 490 491 void ieee802154_compute_header_and_authtag_len(struct net_if *iface, struct net_linkaddr *dst, 492 struct net_linkaddr *src, uint8_t *ll_hdr_len, 493 uint8_t *authtag_len); 494 495 bool ieee802154_create_data_frame(struct ieee802154_context *ctx, struct net_linkaddr *dst, 496 struct net_linkaddr *src, struct net_buf *buf, 497 uint8_t ll_hdr_len); 498 499 struct net_pkt *ieee802154_create_mac_cmd_frame(struct net_if *iface, enum ieee802154_cfi type, 500 struct ieee802154_frame_params *params); 501 502 void ieee802154_mac_cmd_finalize(struct net_pkt *pkt, enum ieee802154_cfi type); 503 ieee802154_get_mac_command(struct net_pkt * pkt)504 static inline struct ieee802154_command *ieee802154_get_mac_command(struct net_pkt *pkt) 505 { 506 return (struct ieee802154_command *)(pkt->frags->data + pkt->frags->len); 507 } 508 509 bool ieee802154_create_ack_frame(struct net_if *iface, struct net_pkt *pkt, uint8_t seq); 510 511 #ifdef CONFIG_NET_L2_IEEE802154_SECURITY 512 bool ieee802154_decipher_data_frame(struct net_if *iface, struct net_pkt *pkt, 513 struct ieee802154_mpdu *mpdu); 514 #else 515 #define ieee802154_decipher_data_frame(...) true 516 #endif /* CONFIG_NET_L2_IEEE802154_SECURITY */ 517 518 #endif /* __IEEE802154_FRAME_H__ */ 519