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