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