2 * Copyright (c) 2017-2020 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
30 * Copyright (c) 2008, Swedish Institute of Computer Science
31 * All rights reserved.
33 * Additional fixes for AVR contributed by:
35 * Colin O'Flynn coflynn@newae.com
36 * Eric Gnoske egnoske@gmail.com
37 * Blake Leverett bleverett@gmail.com
38 * Mike Vidales mavida404@gmail.com
39 * Kevin Brown kbrown3@uccs.edu
40 * Nate Bohlmann nate@elfwerks.com
42 * Additional fixes for MSP430 contributed by:
47 * All rights reserved.
49 * Redistribution and use in source and binary forms, with or without
50 * modification, are permitted provided that the following conditions are met:
52 * * Redistributions of source code must retain the above copyright
53 * notice, this list of conditions and the following disclaimer.
54 * * Redistributions in binary form must reproduce the above copyright
55 * notice, this list of conditions and the following disclaimer in
56 * the documentation and/or other materials provided with the
58 * * Neither the name of the copyright holders nor the names of
59 * contributors may be used to endorse or promote products derived
60 * from this software without specific prior written permission.
62 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
63 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
64 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
65 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
66 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
67 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
68 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
69 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
70 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
71 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
72 * POSSIBILITY OF SUCH DAMAGE.
76 * \brief This file is where the main functions that relate to frame
77 * manipulation will reside.
82 * \brief 802.15.4 frame creation and parsing functions
84 * This file converts to and from a structure to a packed 802.15.4
89 * \addtogroup frame802154
94 #include "frame802154.h"
95 //#include "net/llsec/llsec802154.h"
100 * \brief Structure that contains the lengths of the various addressing and security fields
101 * in the 802.15.4 header. This structure is used in \ref frame802154_create()
104 uint8_t dest_pid_len
; /**< Length (in bytes) of destination PAN ID field */
105 uint8_t dest_addr_len
; /**< Length (in bytes) of destination address field */
106 uint8_t src_pid_len
; /**< Length (in bytes) of source PAN ID field */
107 uint8_t src_addr_len
; /**< Length (in bytes) of source address field */
108 uint8_t aux_sec_len
; /**< Length (in bytes) of aux security header field */
111 /*----------------------------------------------------------------------------*/
112 CC_INLINE
static uint8_t
113 addr_len(uint8_t mode
)
116 case FRAME802154_SHORTADDRMODE
: /* 16-bit address */
118 case FRAME802154_LONGADDRMODE
: /* 64-bit address */
124 /*----------------------------------------------------------------------------*/
125 #if LLSEC802154_USES_EXPLICIT_KEYS
127 get_key_id_len(uint8_t key_id_mode
)
129 switch (key_id_mode
) {
130 case FRAME802154_1_BYTE_KEY_ID_MODE
:
132 case FRAME802154_5_BYTE_KEY_ID_MODE
:
134 case FRAME802154_9_BYTE_KEY_ID_MODE
:
140 #endif /* LLSEC802154_USES_EXPLICIT_KEYS */
141 /*----------------------------------------------------------------------------*/
143 field_len(frame802154_t
*p
, field_length_t
*flen
)
145 /* init flen to zeros */
146 memset(flen
, 0, sizeof(field_length_t
));
148 /* Determine lengths of each field based on fcf and other args */
149 if (p
->fcf
.dest_addr_mode
& 3) {
150 flen
->dest_pid_len
= 2;
152 if (p
->fcf
.src_addr_mode
& 3) {
153 flen
->src_pid_len
= 2;
156 /* Set PAN ID compression bit if src pan id matches dest pan id. */
157 if (p
->fcf
.dest_addr_mode
& 3 && p
->fcf
.src_addr_mode
& 3 &&
158 p
->src_pid
== p
->dest_pid
) {
159 p
->fcf
.panid_compression
= 1;
161 /* compressed header, only do dest pid */
162 flen
->src_pid_len
= 0;
164 p
->fcf
.panid_compression
= 0;
167 /* determine address lengths */
168 flen
->dest_addr_len
= addr_len(p
->fcf
.dest_addr_mode
& 3);
169 flen
->src_addr_len
= addr_len(p
->fcf
.src_addr_mode
& 3);
171 #if LLSEC802154_SECURITY_LEVEL
172 /* Aux security header */
173 if (p
->fcf
.security_enabled
& 1) {
174 flen
->aux_sec_len
= 5
175 #if LLSEC802154_USES_EXPLICIT_KEYS
176 + get_key_id_len(p
->aux_hdr
.security_control
.key_id_mode
);
177 #endif /* LLSEC802154_USES_EXPLICIT_KEYS */
180 #endif /* LLSEC802154_SECURITY_LEVEL */
182 /*----------------------------------------------------------------------------*/
184 * \brief Calculates the length of the frame header. This function is
185 * meant to be called by a higher level function, that interfaces to a MAC.
187 * \param p Pointer to frame802154_t_t struct, which specifies the
190 * \return The length of the frame header.
193 frame802154_hdrlen(frame802154_t
*p
)
197 return 3 + flen
.dest_pid_len
+ flen
.dest_addr_len
+
198 flen
.src_pid_len
+ flen
.src_addr_len
+ flen
.aux_sec_len
;
200 /*----------------------------------------------------------------------------*/
202 * \brief Creates a frame for transmission over the air. This function is
203 * meant to be called by a higher level function, that interfaces to a MAC.
205 * \param p Pointer to frame802154_t struct, which specifies the
208 * \param buf Pointer to the buffer to use for the frame.
210 * \return The length of the frame header
213 frame802154_create(frame802154_t
*p
, uint8_t *buf
)
218 #if LLSEC802154_USES_EXPLICIT_KEYS
220 #endif /* LLSEC802154_USES_EXPLICIT_KEYS */
224 /* OK, now we have field lengths. Time to actually construct */
225 /* the outgoing frame, and store it in buf */
226 buf
[0] = (uint8_t)((p
->fcf
.frame_type
& 7) |
227 ((p
->fcf
.security_enabled
& 1) << 3) |
228 ((p
->fcf
.frame_pending
& 1) << 4) |
229 ((p
->fcf
.ack_required
& 1) << 5) |
230 ((p
->fcf
.panid_compression
& 1) << 6));
231 buf
[1] = (uint8_t)(((p
->fcf
.dest_addr_mode
& 3) << 2) |
232 ((p
->fcf
.frame_version
& 3) << 4) |
233 ((p
->fcf
.src_addr_mode
& 3) << 6));
235 /* sequence number */
239 /* Destination PAN ID */
240 if (flen
.dest_pid_len
== 2) {
241 buf
[pos
++] = p
->dest_pid
& 0xff;
242 buf
[pos
++] = (p
->dest_pid
>> 8) & 0xff;
245 /* Destination address */
246 for (c
= flen
.dest_addr_len
; c
> 0; c
--) {
247 buf
[pos
++] = p
->dest_addr
[c
- 1];
251 if (flen
.src_pid_len
== 2) {
252 buf
[pos
++] = p
->src_pid
& 0xff;
253 buf
[pos
++] = (p
->src_pid
>> 8) & 0xff;
257 for (c
= flen
.src_addr_len
; c
> 0; c
--) {
258 buf
[pos
++] = p
->src_addr
[c
- 1];
261 #if LLSEC802154_SECURITY_LEVEL
263 if (flen
.aux_sec_len
) {
264 buf
[pos
++] = p
->aux_hdr
.security_control
.security_level
265 #if LLSEC802154_USES_EXPLICIT_KEYS
266 | (p
->aux_hdr
.security_control
.key_id_mode
<< 3)
267 #endif /* LLSEC802154_USES_EXPLICIT_KEYS */
269 memcpy(buf
+ pos
, p
->aux_hdr
.frame_counter
.u8
, 4);
272 #if LLSEC802154_USES_EXPLICIT_KEYS
273 key_id_mode
= p
->aux_hdr
.security_control
.key_id_mode
;
275 c
= (key_id_mode
- 1) * 4;
276 memcpy(buf
+ pos
, p
->aux_hdr
.key_source
.u8
, c
);
278 buf
[pos
++] = p
->aux_hdr
.key_index
;
280 #endif /* LLSEC802154_USES_EXPLICIT_KEYS */
282 #endif /* LLSEC802154_SECURITY_LEVEL */
286 /*----------------------------------------------------------------------------*/
288 * \brief Parses an input frame. Scans the input frame to find each
289 * section, and stores the information of each section in a
290 * frame802154_t structure.
292 * \param data The input data from the radio chip.
293 * \param len The size of the input data
294 * \param pf The frame802154_t struct to store the parsed frame information.
297 frame802154_parse(uint8_t *data
, size_t len
, frame802154_t
*pf
, uint8_t **payload
)
300 frame802154_fcf_t fcf
;
302 #if LLSEC802154_USES_EXPLICIT_KEYS
304 #endif /* LLSEC802154_USES_EXPLICIT_KEYS */
313 fcf
.frame_type
= p
[0] & 7;
314 fcf
.security_enabled
= (p
[0] >> 3) & 1;
315 fcf
.frame_pending
= (p
[0] >> 4) & 1;
316 fcf
.ack_required
= (p
[0] >> 5) & 1;
317 fcf
.panid_compression
= (p
[0] >> 6) & 1;
319 fcf
.dest_addr_mode
= (p
[1] >> 2) & 3;
320 fcf
.frame_version
= (p
[1] >> 4) & 3;
321 fcf
.src_addr_mode
= (p
[1] >> 6) & 3;
323 /* copy fcf and seqNum */
324 memcpy(&pf
->fcf
, &fcf
, sizeof(frame802154_fcf_t
));
326 p
+= 3; /* Skip first three bytes */
328 /* Destination address, if any */
329 if (fcf
.dest_addr_mode
) {
330 /* Destination PAN */
331 pf
->dest_pid
= (uint16_t)(p
[0] + (p
[1] << 8));
334 /* Destination address */
335 /* l = addr_len(fcf.dest_addr_mode); */
336 /* for(c = 0; c < l; c++) { */
337 /* pf->dest_addr.u8[c] = p[l - c - 1]; */
340 if (fcf
.dest_addr_mode
== FRAME802154_SHORTADDRMODE
) {
341 linkaddr_copy((linkaddr_t
*)(uintptr_t)&(pf
->dest_addr
), &linkaddr_null
);
342 pf
->dest_addr
[0] = p
[1];
343 pf
->dest_addr
[1] = p
[0];
345 } else if (fcf
.dest_addr_mode
== FRAME802154_LONGADDRMODE
) {
346 for (c
= 0; c
< 8; c
++) {
347 pf
->dest_addr
[c
] = p
[7 - c
];
352 linkaddr_copy((linkaddr_t
*)(uintptr_t)&(pf
->dest_addr
), &linkaddr_null
);
356 /* Source address, if any */
357 if (fcf
.src_addr_mode
) {
359 if (!fcf
.panid_compression
) {
360 pf
->src_pid
= (uint16_t)(p
[0] + (p
[1] << 8));
363 pf
->src_pid
= pf
->dest_pid
;
367 /* l = addr_len(fcf.src_addr_mode); */
368 /* for(c = 0; c < l; c++) { */
369 /* pf->src_addr.u8[c] = p[l - c - 1]; */
372 if (fcf
.src_addr_mode
== FRAME802154_SHORTADDRMODE
) {
373 linkaddr_copy((linkaddr_t
*)(uintptr_t)&(pf
->src_addr
), &linkaddr_null
);
374 pf
->src_addr
[0] = p
[1];
375 pf
->src_addr
[1] = p
[0];
377 } else if (fcf
.src_addr_mode
== FRAME802154_LONGADDRMODE
) {
378 for (c
= 0; c
< 8; c
++) {
379 pf
->src_addr
[c
] = p
[7 - c
];
384 linkaddr_copy((linkaddr_t
*)(uintptr_t)&(pf
->src_addr
), &linkaddr_null
);
388 #if LLSEC802154_SECURITY_LEVEL
389 if (fcf
.security_enabled
) {
390 pf
->aux_hdr
.security_control
.security_level
= p
[0] & 7;
391 #if LLSEC802154_USES_EXPLICIT_KEYS
392 pf
->aux_hdr
.security_control
.key_id_mode
= (p
[0] >> 3) & 3;
393 #endif /* LLSEC802154_USES_EXPLICIT_KEYS */
396 memcpy(pf
->aux_hdr
.frame_counter
.u8
, p
, 4);
399 #if LLSEC802154_USES_EXPLICIT_KEYS
400 key_id_mode
= pf
->aux_hdr
.security_control
.key_id_mode
;
402 c
= (key_id_mode
- 1) * 4;
403 memcpy(pf
->aux_hdr
.key_source
.u8
, p
, c
);
405 pf
->aux_hdr
.key_index
= p
[0];
408 #endif /* LLSEC802154_USES_EXPLICIT_KEYS */
410 #endif /* LLSEC802154_SECURITY_LEVEL */
415 pf
->payload_len
= (int)(len
- c
);
419 /* return header length if successful */
420 return c
> len
? 0 : c
;