Contiki-NG
Loading...
Searching...
No Matches
frame802154.c
Go to the documentation of this file.
1/*
2 *
3 * Copyright (c) 2008, Swedish Institute of Computer Science
4 * All rights reserved.
5 *
6 * Additional fixes for AVR contributed by:
7 *
8 * Colin O'Flynn coflynn@newae.com
9 * Eric Gnoske egnoske@gmail.com
10 * Blake Leverett bleverett@gmail.com
11 * Mike Vidales mavida404@gmail.com
12 * Kevin Brown kbrown3@uccs.edu
13 * Nate Bohlmann nate@elfwerks.com
14 *
15 * Additional fixes for MSP430 contributed by:
16 * Joakim Eriksson
17 * Niclas Finne
18 * Nicolas Tsiftes
19 *
20 * All rights reserved.
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions are met:
24 *
25 * * Redistributions of source code must retain the above copyright
26 * notice, this list of conditions and the following disclaimer.
27 * * Redistributions in binary form must reproduce the above copyright
28 * notice, this list of conditions and the following disclaimer in
29 * the documentation and/or other materials provided with the
30 * distribution.
31 * * Neither the name of the copyright holders nor the names of
32 * contributors may be used to endorse or promote products derived
33 * from this software without specific prior written permission.
34 *
35 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
36 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
39 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
40 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
41 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
42 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
43 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
44 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
45 * POSSIBILITY OF SUCH DAMAGE.
46 *
47 */
48/*
49 * \brief This file is where the main functions that relate to frame
50 * manipulation will reside.
51 */
52
53/**
54 * \file
55 * \brief 802.15.4 frame creation and parsing functions
56 *
57 * This file converts to and from a structure to a packed 802.15.4
58 * frame.
59 */
60
61/**
62 * \addtogroup frame802154
63 * @{
64 */
65
66#include "sys/cc.h"
68#include "net/mac/llsec802154.h"
69#include "net/linkaddr.h"
70#include <string.h>
71
72/** \brief The 16-bit identifier of the PAN on which the device is
73 * operating. If this value is 0xffff, the device is not
74 * associated.
75 */
76static uint16_t mac_pan_id = IEEE802154_PANID;
77
78/**
79 * \brief Structure that contains the lengths of the various addressing and security fields
80 * in the 802.15.4 header. This structure is used in \ref frame802154_create()
81 */
82typedef struct {
83 uint8_t frame_ctrl_len; /**< Length (in bytes) of the frame control field */
84 uint8_t seqno_len; /**< Length (in bytes) of sequence number field */
85 uint8_t dest_pid_len; /**< Length (in bytes) of destination PAN ID field */
86 uint8_t dest_addr_len; /**< Length (in bytes) of destination address field */
87 uint8_t src_pid_len; /**< Length (in bytes) of source PAN ID field */
88 uint8_t src_addr_len; /**< Length (in bytes) of source address field */
89 uint8_t aux_sec_len; /**< Length (in bytes) of aux security header field */
90} field_length_t;
91
92/*----------------------------------------------------------------------------*/
93static inline uint8_t
94addr_len(uint8_t mode)
95{
96 switch(mode) {
97 case FRAME802154_SHORTADDRMODE: /* 16-bit address */
98 return 2;
99 case FRAME802154_LONGADDRMODE: /* 64-bit address */
100 return 8;
101 default:
102 return 0;
103 }
104}
105/*----------------------------------------------------------------------------*/
106#if LLSEC802154_USES_AUX_HEADER && LLSEC802154_USES_EXPLICIT_KEYS
107static uint8_t
108get_key_id_len(uint8_t key_id_mode)
109{
110 switch(key_id_mode) {
111 case FRAME802154_1_BYTE_KEY_ID_MODE:
112 return 1;
113 case FRAME802154_5_BYTE_KEY_ID_MODE:
114 return 5;
115 case FRAME802154_9_BYTE_KEY_ID_MODE:
116 return 9;
117 default:
118 return 0;
119 }
120}
121#endif /* LLSEC802154_USES_AUX_HEADER && LLSEC802154_USES_EXPLICIT_KEYS */
122/*---------------------------------------------------------------------------*/
123/* Get current PAN ID */
124uint16_t
125frame802154_get_pan_id(void)
126{
127 return mac_pan_id;
128}
129/*---------------------------------------------------------------------------*/
130/* Set current PAN ID */
131void
132frame802154_set_pan_id(uint16_t pan_id)
133{
134 mac_pan_id = pan_id;
135}
136/*----------------------------------------------------------------------------*/
137/* Tells whether a given Frame Control Field indicates a frame with
138 * source PANID and/or destination PANID */
139void
140frame802154_has_panid(frame802154_fcf_t *fcf, int *has_src_pan_id, int *has_dest_pan_id)
141{
142 int src_pan_id = 0;
143 int dest_pan_id = 0;
144
145 if(fcf == NULL) {
146 return;
147 }
148
149 if(fcf->frame_version == FRAME802154_IEEE802154_2015) {
150 if(fcf->frame_type == FRAME802154_MPFRAME) {
151 *has_src_pan_id = 0;
152 *has_dest_pan_id = !fcf->panid_compression;
153 return;
154 }
155
156 /*
157 * IEEE 802.15.4-2015
158 * Table 7-2, PAN ID Compression value for frame version 0b10
159 */
162 fcf->panid_compression == 1) ||
165 fcf->panid_compression == 0) ||
166 (fcf->dest_addr_mode == FRAME802154_LONGADDRMODE &&
167 fcf->src_addr_mode == FRAME802154_LONGADDRMODE &&
168 fcf->panid_compression == 0) ||
169 ((fcf->dest_addr_mode == FRAME802154_SHORTADDRMODE &&
172 fcf->src_addr_mode == FRAME802154_SHORTADDRMODE)) ){
173 dest_pan_id = 1;
174 }
175
176 if(fcf->panid_compression == 0 &&
178 fcf->src_addr_mode == FRAME802154_LONGADDRMODE) ||
180 fcf->src_addr_mode == FRAME802154_SHORTADDRMODE) ||
181 (fcf->dest_addr_mode == FRAME802154_SHORTADDRMODE &&
182 fcf->src_addr_mode == FRAME802154_SHORTADDRMODE) ||
183 (fcf->dest_addr_mode == FRAME802154_SHORTADDRMODE &&
184 fcf->src_addr_mode == FRAME802154_LONGADDRMODE) ||
185 (fcf->dest_addr_mode == FRAME802154_LONGADDRMODE &&
186 fcf->src_addr_mode == FRAME802154_SHORTADDRMODE))) {
187 src_pan_id = 1;
188 }
189
190 } else {
191 /* No PAN ID in ACK */
192 if(fcf->frame_type != FRAME802154_ACKFRAME) {
193 if(!fcf->panid_compression && (fcf->src_addr_mode & 3)) {
194 /* If compressed, don't include source PAN ID */
195 src_pan_id = 1;
196 }
197 if(fcf->dest_addr_mode & 3) {
198 dest_pan_id = 1;
199 }
200 }
201 }
202
203 if(has_src_pan_id != NULL) {
204 *has_src_pan_id = src_pan_id;
205 }
206 if(has_dest_pan_id != NULL) {
207 *has_dest_pan_id = dest_pan_id;
208 }
209}
210/*---------------------------------------------------------------------------*/
211/* Check if the destination PAN ID, if any, matches ours */
212int
213frame802154_check_dest_panid(frame802154_t *frame)
214{
215 int has_dest_panid = 0;
216
217 if(frame == NULL) {
218 return 0;
219 }
220 frame802154_has_panid(&frame->fcf, NULL, &has_dest_panid);
221 if(!has_dest_panid ||
222 (frame->dest_pid != frame802154_get_pan_id()
223 && frame->dest_pid != FRAME802154_BROADCASTPANDID)) {
224 /* Packet to another PAN */
225 return 0;
226 }
227 return 1;
228}
229/*---------------------------------------------------------------------------*/
230/* Check is the address is a broadcast address, whatever its size */
231bool
232frame802154_is_broadcast_addr(uint8_t mode, const uint8_t *addr)
233{
234 int i = mode == FRAME802154_SHORTADDRMODE ? 2 : 8;
235 while(i-- > 0) {
236 if(addr[i] != 0xff) {
237 return false;
238 }
239 }
240 return true;
241}
242/*---------------------------------------------------------------------------*/
243/* Check and extract source and destination linkaddr from frame */
244int
245frame802154_extract_linkaddr(frame802154_t *frame,
246 linkaddr_t *source_address, linkaddr_t *dest_address)
247{
248 int src_addr_len;
249 int dest_addr_len;
250
251 if(frame == NULL) {
252 return 0;
253 }
254 /* Check and extract source address */
255 src_addr_len = frame->fcf.src_addr_mode ?
256 ((frame->fcf.src_addr_mode == FRAME802154_SHORTADDRMODE) ? 2 : 8) : 0;
257 if(src_addr_len == 0 || frame802154_is_broadcast_addr(frame->fcf.src_addr_mode, frame->src_addr)) {
258 /* Broadcast address */
259 if(source_address != NULL) {
260 linkaddr_copy(source_address, &linkaddr_null);
261 }
262 } else {
263 /* Unicast address */
264 if(src_addr_len != LINKADDR_SIZE) {
265 /* Source address has a size we can not handle */
266 return 0;
267 }
268 if(source_address != NULL) {
269 linkaddr_copy(source_address, (linkaddr_t *)frame->src_addr);
270 }
271 }
272
273 /* Check and extract destination address */
274 dest_addr_len = frame->fcf.dest_addr_mode ?
275 ((frame->fcf.dest_addr_mode == FRAME802154_SHORTADDRMODE) ? 2 : 8) : 0;
276 if(dest_addr_len == 0 || frame802154_is_broadcast_addr(frame->fcf.dest_addr_mode, frame->dest_addr)) {
277 /* Broadcast address */
278 if(dest_address != NULL) {
279 linkaddr_copy(dest_address, &linkaddr_null);
280 }
281 } else {
282 /* Unicast address */
283 if(dest_addr_len != LINKADDR_SIZE) {
284 /* Destination address has a size we can not handle */
285 return 0;
286 }
287 if(dest_address != NULL) {
288 linkaddr_copy(dest_address, (linkaddr_t *)frame->dest_addr);
289 }
290 }
291
292 return 1;
293}
294/*----------------------------------------------------------------------------*/
295static void
296field_len(frame802154_t *p, field_length_t *flen)
297{
298 int has_src_panid;
299 int has_dest_panid;
300
301 /* init flen to zeros */
302 memset(flen, 0, sizeof(field_length_t));
303
304 flen->frame_ctrl_len =
305 (p->fcf.frame_type == FRAME802154_MPFRAME) && !p->fcf.long_frame_control
306 ? 1
307 : 2;
308
309 /* Determine lengths of each field based on fcf and other args */
310 if((p->fcf.sequence_number_suppression & 1) == 0) {
311 flen->seqno_len = 1;
312 }
313
314 /* IEEE802.15.4e changes the meaning of PAN ID Compression (see Table 2a).
315 * In this case, we leave the decision whether to compress PAN ID or not
316 * up to the caller. */
317 if(p->fcf.frame_version < FRAME802154_IEEE802154_2015) {
318 /* Set PAN ID compression bit if src pan id matches dest pan id. */
319 p->fcf.panid_compression = (p->fcf.dest_addr_mode & 3) &&
320 (p->fcf.src_addr_mode & 3) && p->src_pid == p->dest_pid;
321 }
322
323 frame802154_has_panid(&p->fcf, &has_src_panid, &has_dest_panid);
324
325 if(has_src_panid) {
326 flen->src_pid_len = 2;
327 }
328
329 if(has_dest_panid) {
330 flen->dest_pid_len = 2;
331 }
332
333 /* determine address lengths */
334 flen->dest_addr_len = addr_len(p->fcf.dest_addr_mode & 3);
335 flen->src_addr_len = addr_len(p->fcf.src_addr_mode & 3);
336
337#if LLSEC802154_USES_AUX_HEADER
338 /* Aux security header */
339 if(p->fcf.security_enabled & 1) {
340 flen->aux_sec_len = 1; /* FCF + possibly frame counter and key ID */
341 if(p->aux_hdr.security_control.frame_counter_suppression == 0) {
342 if(p->aux_hdr.security_control.frame_counter_size == 1) {
343 flen->aux_sec_len += 5;
344 } else {
345 flen->aux_sec_len += 4;
346 }
347 }
348#if LLSEC802154_USES_EXPLICIT_KEYS
349 flen->aux_sec_len += get_key_id_len(p->aux_hdr.security_control.key_id_mode);
350#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
351 }
352#endif /* LLSEC802154_USES_AUX_HEADER */
353}
354/*----------------------------------------------------------------------------*/
355/**
356 * \brief Calculates the length of the frame header. This function is
357 * meant to be called by a higher level function, that interfaces to a MAC.
358 *
359 * \param p Pointer to frame802154_t_t struct, which specifies the
360 * frame to send.
361 *
362 * \return The length of the frame header.
363 */
364int
366{
367 field_length_t flen;
368 field_len(p, &flen);
369 return flen.frame_ctrl_len
370 + flen.seqno_len
371 + flen.dest_pid_len
372 + flen.dest_addr_len
373 + flen.src_pid_len
374 + flen.src_addr_len
375 + flen.aux_sec_len;
376}
377/*----------------------------------------------------------------------------*/
378int
379frame802154_create_fcf(frame802154_fcf_t *fcf, uint8_t *buf)
380{
381#if FRAME802154_VERSION == FRAME802154_IEEE802154_2015
382 if(fcf->frame_type == FRAME802154_MPFRAME) {
383 /* create MP Frame Control field */
384 buf[0] = FRAME802154_MPFRAME
385 | ((fcf->long_frame_control) << 3)
386 | ((fcf->dest_addr_mode & 3) << 4)
387 | ((fcf->src_addr_mode & 3) << 6);
388 if(!fcf->long_frame_control) {
389 return 1;
390 }
391 buf[1] = ((!fcf->panid_compression) & 1)
392 | ((fcf->security_enabled & 1) << 1)
393 | ((fcf->sequence_number_suppression & 1) << 2)
394 | ((fcf->frame_pending & 1) << 3)
395 | ((fcf->ack_required & 1) << 6)
396 | ((fcf->ie_list_present & 1) << 7);
397 return 2;
398 }
399#endif /* FRAME802154_VERSION == FRAME802154_IEEE802154_2015 */
400 /* create Frame Control field */
401 buf[0] = (fcf->frame_type & 7) |
402 ((fcf->security_enabled & 1) << 3) |
403 ((fcf->frame_pending & 1) << 4) |
404 ((fcf->ack_required & 1) << 5) |
405 ((fcf->panid_compression & 1) << 6);
406 buf[1] = ((fcf->sequence_number_suppression & 1)) |
407 ((fcf->ie_list_present & 1)) << 1 |
408 ((fcf->dest_addr_mode & 3) << 2) |
409 ((fcf->frame_version & 3) << 4) |
410 ((fcf->src_addr_mode & 3) << 6);
411 return 2;
412}
413/*----------------------------------------------------------------------------*/
414/**
415 * \brief Creates a frame for transmission over the air. This function is
416 * meant to be called by a higher level function, that interfaces to a MAC.
417 *
418 * \param p Pointer to frame802154_t struct, which specifies the
419 * frame to send.
420 *
421 * \param buf Pointer to the buffer to use for the frame.
422 *
423 * \return The length of the frame header
424 */
425int
427{
428 int c;
429 field_length_t flen;
430#if LLSEC802154_USES_EXPLICIT_KEYS
431 uint8_t key_id_mode;
432#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
433
434 field_len(p, &flen);
435
436 /* OK, now we have field lengths. Time to actually construct */
437 /* the outgoing frame, and store it in buf */
438 unsigned int pos = frame802154_create_fcf(&p->fcf, buf);
439
440 /* Sequence number */
441 if(flen.seqno_len == 1) {
442 buf[pos++] = p->seq;
443 }
444
445 /* Destination PAN ID */
446 if(flen.dest_pid_len == 2) {
447 buf[pos++] = p->dest_pid & 0xff;
448 buf[pos++] = (p->dest_pid >> 8) & 0xff;
449 }
450
451 /* Destination address */
452 for(c = flen.dest_addr_len; c > 0; c--) {
453 buf[pos++] = p->dest_addr[c - 1];
454 }
455
456 /* Source PAN ID */
457 if(flen.src_pid_len == 2) {
458 buf[pos++] = p->src_pid & 0xff;
459 buf[pos++] = (p->src_pid >> 8) & 0xff;
460 }
461
462 /* Source address */
463 for(c = flen.src_addr_len; c > 0; c--) {
464 buf[pos++] = p->src_addr[c - 1];
465 }
466#if LLSEC802154_USES_AUX_HEADER
467 /* Aux header */
468 if(flen.aux_sec_len) {
469 buf[pos++] = p->aux_hdr.security_control.security_level
470#if LLSEC802154_USES_EXPLICIT_KEYS
471 | (p->aux_hdr.security_control.key_id_mode << 3)
472#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
473 | (p->aux_hdr.security_control.frame_counter_suppression << 5)
474 | (p->aux_hdr.security_control.frame_counter_size << 6)
475 ;
476 if(p->aux_hdr.security_control.frame_counter_suppression == 0) {
477 /* We support only 4-byte counters */
478 memcpy(buf + pos, p->aux_hdr.frame_counter.u8, 4);
479 pos += 4;
480 if(p->aux_hdr.security_control.frame_counter_size == 1) {
481 pos++;
482 }
483 }
484
485#if LLSEC802154_USES_EXPLICIT_KEYS
486 key_id_mode = p->aux_hdr.security_control.key_id_mode;
487 if(key_id_mode) {
488 c = (key_id_mode - 1) * 4;
489 memcpy(buf + pos, p->aux_hdr.key_source.u8, c);
490 pos += c;
491 buf[pos++] = p->aux_hdr.key_index;
492 }
493#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
494 }
495#endif /* LLSEC802154_USES_AUX_HEADER */
496
497 return (int)pos;
498}
499/*----------------------------------------------------------------------------*/
500int
501frame802154_parse_fcf(const uint8_t *data, frame802154_fcf_t *pfcf)
502{
503 /* parse Frame Type field */
504 pfcf->frame_type = data[0] & 7;
505
506 switch(pfcf->frame_type) {
507 case FRAME802154_MPFRAME:
508 /* parse MP Frame Control field */
509 pfcf->long_frame_control = (data[0] >> 3) & 1;
510 pfcf->dest_addr_mode = (data[0] >> 4) & 3;
511 pfcf->src_addr_mode = (data[0] >> 6) & 3;
512
513 if(!pfcf->long_frame_control) {
514 return 1;
515 }
516 pfcf->panid_compression = !(data[1] & 1);
517 pfcf->security_enabled = (data[1] >> 1) & 1;
518 pfcf->sequence_number_suppression = (data[1] >> 2) & 1;
519 pfcf->frame_pending = (data[1] >> 3) & 1;
520 pfcf->frame_version = (data[1] >> 4) & 3;
521 pfcf->ack_required = (data[1] >> 6) & 1;
522 pfcf->ie_list_present = (data[1] >> 7) & 1;
523 return 2;
524 default:
525 /* parse Frame Control field */
526 pfcf->security_enabled = (data[0] >> 3) & 1;
527 pfcf->frame_pending = (data[0] >> 4) & 1;
528 pfcf->ack_required = (data[0] >> 5) & 1;
529 pfcf->panid_compression = (data[0] >> 6) & 1;
530
531 pfcf->sequence_number_suppression = data[1] & 1;
532 pfcf->ie_list_present = (data[1] >> 1) & 1;
533 pfcf->dest_addr_mode = (data[1] >> 2) & 3;
534 pfcf->frame_version = (data[1] >> 4) & 3;
535 pfcf->src_addr_mode = (data[1] >> 6) & 3;
536 return 2;
537 }
538}
539/*----------------------------------------------------------------------------*/
540/*
541 * Ensure at least n more bytes remain in the input before reading them.
542 * Used throughout frame802154_parse() to bound every field access against
543 * the declared frame length, so a truncated frame whose FCF advertises a
544 * large header (addressing and/or auxiliary security) cannot cause reads
545 * past the end of the input buffer.
546 */
547#define REQUIRE_BYTES(n) do { \
548 if((p - data) + (n) > len) { \
549 return 0; \
550 } \
551 } while(0)
552/*----------------------------------------------------------------------------*/
553/**
554 * \brief Parses an input frame. Scans the input frame to find each
555 * section, and stores the information of each section in a
556 * frame802154_t structure.
557 *
558 * \param data The input data from the radio chip.
559 * \param len The size of the input data
560 * \param pf The frame802154_t struct to store the parsed frame information.
561 */
562int
563frame802154_parse(uint8_t *data, int len, frame802154_t *pf)
564{
565 uint8_t *p;
566 int c;
567 int has_src_panid;
568 int has_dest_panid;
569#if LLSEC802154_USES_EXPLICIT_KEYS
570 uint8_t key_id_mode;
571#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
572
573 if(len < 2) {
574 return 0;
575 }
576
577 p = data;
578
579 /* decode the FCF */
580 p += frame802154_parse_fcf(p, &pf->fcf);
581
582 if(pf->fcf.sequence_number_suppression == 0) {
583 REQUIRE_BYTES(1);
584 pf->seq = p[0];
585 p++;
586 }
587
588 frame802154_has_panid(&pf->fcf, &has_src_panid, &has_dest_panid);
589
590 /* Destination address, if any */
591 if(pf->fcf.dest_addr_mode) {
592 if(has_dest_panid) {
593 /* Destination PAN */
594 REQUIRE_BYTES(2);
595 pf->dest_pid = p[0] + (p[1] << 8);
596 p += 2;
597 } else {
598 pf->dest_pid = 0;
599 }
600
601 /* Destination address */
602 if(pf->fcf.dest_addr_mode == FRAME802154_SHORTADDRMODE) {
603 REQUIRE_BYTES(2);
604 linkaddr_copy((linkaddr_t *)&(pf->dest_addr), &linkaddr_null);
605 pf->dest_addr[0] = p[1];
606 pf->dest_addr[1] = p[0];
607 p += 2;
608 } else if(pf->fcf.dest_addr_mode == FRAME802154_LONGADDRMODE) {
609 REQUIRE_BYTES(8);
610 for(c = 0; c < 8; c++) {
611 pf->dest_addr[c] = p[7 - c];
612 }
613 p += 8;
614 }
615 } else {
616 linkaddr_copy((linkaddr_t *)&(pf->dest_addr), &linkaddr_null);
617 pf->dest_pid = 0;
618 }
619
620 /* Source address, if any */
621 if(pf->fcf.src_addr_mode) {
622 /* Source PAN */
623 if(has_src_panid) {
624 REQUIRE_BYTES(2);
625 pf->src_pid = p[0] + (p[1] << 8);
626 p += 2;
627 if(!has_dest_panid) {
628 pf->dest_pid = pf->src_pid;
629 }
630 } else {
631 pf->src_pid = pf->dest_pid;
632 }
633
634 /* Source address */
635 if(pf->fcf.src_addr_mode == FRAME802154_SHORTADDRMODE) {
636 REQUIRE_BYTES(2);
637 linkaddr_copy((linkaddr_t *)&(pf->src_addr), &linkaddr_null);
638 pf->src_addr[0] = p[1];
639 pf->src_addr[1] = p[0];
640 p += 2;
641 } else if(pf->fcf.src_addr_mode == FRAME802154_LONGADDRMODE) {
642 REQUIRE_BYTES(8);
643 for(c = 0; c < 8; c++) {
644 pf->src_addr[c] = p[7 - c];
645 }
646 p += 8;
647 }
648 } else {
649 linkaddr_copy((linkaddr_t *)&(pf->src_addr), &linkaddr_null);
650 pf->src_pid = 0;
651 }
652
653#if LLSEC802154_USES_AUX_HEADER
654 if(pf->fcf.security_enabled) {
655 REQUIRE_BYTES(1);
657#if LLSEC802154_USES_EXPLICIT_KEYS
658 pf->aux_hdr.security_control.key_id_mode = (p[0] >> 3) & 3;
659#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
661 pf->aux_hdr.security_control.frame_counter_size = (p[0] >> 6) & 1;
662 p += 1;
663
665 REQUIRE_BYTES(4);
666 memcpy(pf->aux_hdr.frame_counter.u8, p, 4);
667 p += 4;
669 REQUIRE_BYTES(1);
670 p ++;
671 }
672 }
673
674#if LLSEC802154_USES_EXPLICIT_KEYS
675 key_id_mode = pf->aux_hdr.security_control.key_id_mode;
676 if(key_id_mode) {
677 c = (key_id_mode - 1) * 4;
678 REQUIRE_BYTES(c + 1);
679 memcpy(pf->aux_hdr.key_source.u8, p, c);
680 p += c;
681 pf->aux_hdr.key_index = p[0];
682 p += 1;
683 }
684#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
685 }
686#endif /* LLSEC802154_USES_AUX_HEADER */
687
688 /* header length */
689 c = p - data;
690 /* payload length */
691 pf->payload_len = (len - c);
692 /* payload */
693 pf->payload = p;
694
695 /* return header length if successful */
696 return c > len ? 0 : c;
697}
698#undef REQUIRE_BYTES
699/** \} */
Default definitions of C compiler quirk work-arounds.
802.15.4 frame creation and parsing functions
int frame802154_parse(uint8_t *data, int len, frame802154_t *pf)
Parses an input frame.
#define FRAME802154_NOADDR
Only valid for ACK or Beacon frames.
int frame802154_create(frame802154_t *p, uint8_t *buf)
Creates a frame for transmission over the air.
int frame802154_hdrlen(frame802154_t *p)
Calculates the length of the frame header.
static uint16_t mac_pan_id
The 16-bit identifier of the PAN on which the device is operating.
Definition frame802154.c:76
void linkaddr_copy(linkaddr_t *dest, const linkaddr_t *src)
Copy a link-layer address.
Definition linkaddr.c:63
const linkaddr_t linkaddr_null
The null link-layer address.
Header file for the link-layer address representation.
Common functionality of 802.15.4-compliant llsec_drivers.
frame802154_scf_t security_control
Security control bitfield.
frame802154_frame_counter_t frame_counter
Frame counter, used for security.
uint8_t key_index
Key Index subfield.
frame802154_key_source_t key_source
Key Source subfield.
The IEEE 802.15.4 frame has a number of constant/fixed fields that can be counted to make frame const...
uint8_t long_frame_control
1 bit.
uint8_t frame_type
3 bit.
uint8_t frame_version
2 bit.
uint8_t ie_list_present
1 bit.
uint8_t security_enabled
1 bit.
uint8_t sequence_number_suppression
< 1 bit.
uint8_t src_addr_mode
2 bit.
uint8_t panid_compression
1 bit.
uint8_t ack_required
1 bit.
uint8_t dest_addr_mode
2 bit.
uint8_t frame_pending
1 bit.
uint8_t key_id_mode
2 bit.
uint8_t frame_counter_size
1 bit.
uint8_t frame_counter_suppression
1 bit.
uint8_t security_level
3 bit.
Parameters used by the frame802154_create() function.
uint8_t seq
Sequence number.
uint8_t dest_addr[8]
Destination address.
frame802154_aux_hdr_t aux_hdr
Aux security header.
uint8_t * payload
Pointer to 802.15.4 payload.
uint8_t src_addr[8]
Source address.
uint16_t src_pid
Source PAN ID.
frame802154_fcf_t fcf
Frame control field.
uint16_t dest_pid
Destination PAN ID.
int payload_len
Length of payload field.
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition uip-nd6.c:107