Added support for IEEE 802.15.4 frame version 2
This commit is contained in:
parent
f86494c6aa
commit
5cf9871d5b
|
@ -85,6 +85,12 @@
|
||||||
#define LLSEC802154_USES_EXPLICIT_KEYS 0
|
#define LLSEC802154_USES_EXPLICIT_KEYS 0
|
||||||
#endif /* LLSEC802154_CONF_USES_EXPLICIT_KEYS */
|
#endif /* LLSEC802154_CONF_USES_EXPLICIT_KEYS */
|
||||||
|
|
||||||
|
#ifdef LLSEC802154_CONF_USES_FRAME_COUNTER
|
||||||
|
#define LLSEC802154_USES_FRAME_COUNTER LLSEC802154_CONF_USES_FRAME_COUNTER
|
||||||
|
#else /* LLSEC802154_CONF_USES_FRAME_COUNTER */
|
||||||
|
#define LLSEC802154_USES_FRAME_COUNTER (LLSEC802154_SECURITY_LEVEL != FRAME802154_SECURITY_LEVEL_NONE)
|
||||||
|
#endif /* LLSEC802154_CONF_USES_FRAME_COUNTER */
|
||||||
|
|
||||||
#if UIP_BYTE_ORDER == UIP_LITTLE_ENDIAN
|
#if UIP_BYTE_ORDER == UIP_LITTLE_ENDIAN
|
||||||
#define LLSEC802154_HTONS(n) (n)
|
#define LLSEC802154_HTONS(n) (n)
|
||||||
#define LLSEC802154_HTONL(n) (n)
|
#define LLSEC802154_HTONL(n) (n)
|
||||||
|
|
|
@ -69,11 +69,18 @@
|
||||||
#include "net/linkaddr.h"
|
#include "net/linkaddr.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
/** \brief The 16-bit identifier of the PAN on which the device is
|
||||||
|
* operating. If this value is 0xffff, the device is not
|
||||||
|
* associated.
|
||||||
|
*/
|
||||||
|
static uint16_t mac_pan_id = IEEE802154_PANID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Structure that contains the lengths of the various addressing and security fields
|
* \brief Structure that contains the lengths of the various addressing and security fields
|
||||||
* in the 802.15.4 header. This structure is used in \ref frame802154_create()
|
* in the 802.15.4 header. This structure is used in \ref frame802154_create()
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
uint8_t seqno_len; /**< Length (in bytes) of sequence number field */
|
||||||
uint8_t dest_pid_len; /**< Length (in bytes) of destination PAN ID field */
|
uint8_t dest_pid_len; /**< Length (in bytes) of destination PAN ID field */
|
||||||
uint8_t dest_addr_len; /**< Length (in bytes) of destination address field */
|
uint8_t dest_addr_len; /**< Length (in bytes) of destination address field */
|
||||||
uint8_t src_pid_len; /**< Length (in bytes) of source PAN ID field */
|
uint8_t src_pid_len; /**< Length (in bytes) of source PAN ID field */
|
||||||
|
@ -111,31 +118,200 @@ get_key_id_len(uint8_t key_id_mode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
|
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/* Get current PAN ID */
|
||||||
|
uint16_t
|
||||||
|
frame802154_get_pan_id(void)
|
||||||
|
{
|
||||||
|
return mac_pan_id;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/* Set current PAN ID */
|
||||||
|
void
|
||||||
|
frame802154_set_pan_id(uint16_t pan_id)
|
||||||
|
{
|
||||||
|
mac_pan_id = pan_id;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
/* Tells whether a given Frame Control Field indicates a frame with
|
||||||
|
* source PANID and/or destination PANID */
|
||||||
|
void
|
||||||
|
frame802154_has_panid(frame802154_fcf_t *fcf, int *has_src_pan_id, int *has_dest_pan_id)
|
||||||
|
{
|
||||||
|
int src_pan_id = 0;
|
||||||
|
int dest_pan_id = 0;
|
||||||
|
|
||||||
|
if(fcf == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fcf->frame_version == FRAME802154_IEEE802154E_2012) {
|
||||||
|
if(!fcf->panid_compression) {
|
||||||
|
/* Compressed PAN ID == no PAN ID at all */
|
||||||
|
if(fcf->dest_addr_mode == fcf->dest_addr_mode) {
|
||||||
|
/* No address or both addresses: include destination PAN ID */
|
||||||
|
dest_pan_id = 1;
|
||||||
|
} else if(fcf->dest_addr_mode) {
|
||||||
|
/* Only dest address, include dest PAN ID */
|
||||||
|
dest_pan_id = 1;
|
||||||
|
} else if(fcf->src_addr_mode) {
|
||||||
|
/* Only src address, include src PAN ID */
|
||||||
|
src_pan_id = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(fcf->dest_addr_mode == 0 && fcf->dest_addr_mode == 1) {
|
||||||
|
/* No address included, include dest PAN ID conditionally */
|
||||||
|
if(!fcf->panid_compression) {
|
||||||
|
dest_pan_id = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Remove the following rule the day rows 2 and 3 from table 2a are fixed: */
|
||||||
|
if(fcf->dest_addr_mode == 0 && fcf->dest_addr_mode == 0) {
|
||||||
|
/* Not meaningful, we include a PAN ID iff the compress flag is set, but
|
||||||
|
* this is what the standard currently stipulates */
|
||||||
|
dest_pan_id = fcf->panid_compression;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* No PAN ID in ACK */
|
||||||
|
if(fcf->frame_type != FRAME802154_ACKFRAME) {
|
||||||
|
if(!fcf->panid_compression && fcf->src_addr_mode & 3) {
|
||||||
|
/* If compressed, don't inclue source PAN ID */
|
||||||
|
src_pan_id = 1;
|
||||||
|
}
|
||||||
|
if(fcf->dest_addr_mode & 3) {
|
||||||
|
dest_pan_id = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(has_src_pan_id != NULL) {
|
||||||
|
*has_src_pan_id = src_pan_id;
|
||||||
|
}
|
||||||
|
if(has_dest_pan_id != NULL) {
|
||||||
|
*has_dest_pan_id = dest_pan_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/* Check if the destination PAN ID, if any, matches ours */
|
||||||
|
int
|
||||||
|
frame802154_check_dest_panid(frame802154_t *frame)
|
||||||
|
{
|
||||||
|
int has_dest_panid;
|
||||||
|
|
||||||
|
if(frame == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
frame802154_has_panid(&frame->fcf, NULL, &has_dest_panid);
|
||||||
|
if(has_dest_panid
|
||||||
|
&& frame->dest_pid != frame802154_get_pan_id()
|
||||||
|
&& frame->dest_pid != FRAME802154_BROADCASTPANDID) {
|
||||||
|
/* Packet to another PAN */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/* Check is the address is a broadcast address, whatever its size */
|
||||||
|
int
|
||||||
|
frame802154_is_broadcast_addr(uint8_t mode, uint8_t *addr)
|
||||||
|
{
|
||||||
|
int i = mode == FRAME802154_SHORTADDRMODE ? 2 : 8;
|
||||||
|
while(i-- > 0) {
|
||||||
|
if(addr[i] != 0xff) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/* Check and extract source and destination linkaddr from frame */
|
||||||
|
int
|
||||||
|
frame802154_extract_linkaddr(frame802154_t *frame,
|
||||||
|
linkaddr_t *source_address, linkaddr_t *dest_address)
|
||||||
|
{
|
||||||
|
int src_addr_len;
|
||||||
|
int dest_addr_len;
|
||||||
|
|
||||||
|
if(frame == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Check and extract source address */
|
||||||
|
src_addr_len = frame->fcf.src_addr_mode ?
|
||||||
|
((frame->fcf.src_addr_mode == FRAME802154_SHORTADDRMODE) ? 2 : 8) : 0;
|
||||||
|
if(src_addr_len == 0 || frame802154_is_broadcast_addr(frame->fcf.src_addr_mode, frame->src_addr)) {
|
||||||
|
/* Broadcast address */
|
||||||
|
if(source_address != NULL) {
|
||||||
|
linkaddr_copy(source_address, &linkaddr_null);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Unicast address */
|
||||||
|
if(src_addr_len != LINKADDR_SIZE) {
|
||||||
|
/* Destination address has a size we can not handle */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(source_address != NULL) {
|
||||||
|
linkaddr_copy(source_address, (linkaddr_t *)frame->src_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check and extract destination address */
|
||||||
|
dest_addr_len = frame->fcf.dest_addr_mode ?
|
||||||
|
((frame->fcf.dest_addr_mode == FRAME802154_SHORTADDRMODE) ? 2 : 8) : 0;
|
||||||
|
if(dest_addr_len == 0 || frame802154_is_broadcast_addr(frame->fcf.dest_addr_mode, frame->dest_addr)) {
|
||||||
|
/* Broadcast address */
|
||||||
|
if(dest_address != NULL) {
|
||||||
|
linkaddr_copy(dest_address, &linkaddr_null);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Unicast address */
|
||||||
|
if(dest_addr_len != LINKADDR_SIZE) {
|
||||||
|
/* Destination address has a size we can not handle */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(dest_address != NULL) {
|
||||||
|
linkaddr_copy(dest_address, (linkaddr_t *)frame->dest_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
static void
|
static void
|
||||||
field_len(frame802154_t *p, field_length_t *flen)
|
field_len(frame802154_t *p, field_length_t *flen)
|
||||||
{
|
{
|
||||||
|
int has_src_panid;
|
||||||
|
int has_dest_panid;
|
||||||
|
|
||||||
/* init flen to zeros */
|
/* init flen to zeros */
|
||||||
memset(flen, 0, sizeof(field_length_t));
|
memset(flen, 0, sizeof(field_length_t));
|
||||||
|
|
||||||
/* Determine lengths of each field based on fcf and other args */
|
/* Determine lengths of each field based on fcf and other args */
|
||||||
if(p->fcf.dest_addr_mode & 3) {
|
if((p->fcf.sequence_number_suppression & 1) == 0) {
|
||||||
flen->dest_pid_len = 2;
|
flen->seqno_len = 1;
|
||||||
}
|
|
||||||
if(p->fcf.src_addr_mode & 3) {
|
|
||||||
flen->src_pid_len = 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* IEEE802.15.4e changes the meaning of PAN ID Compression (see Table 2a).
|
||||||
|
* In this case, we leave the decision whether to compress PAN ID or not
|
||||||
|
* up to the caller. */
|
||||||
|
if(p->fcf.frame_version < FRAME802154_IEEE802154E_2012) {
|
||||||
/* Set PAN ID compression bit if src pan id matches dest pan id. */
|
/* Set PAN ID compression bit if src pan id matches dest pan id. */
|
||||||
if(p->fcf.dest_addr_mode & 3 && p->fcf.src_addr_mode & 3 &&
|
if(p->fcf.dest_addr_mode & 3 && p->fcf.src_addr_mode & 3 &&
|
||||||
p->src_pid == p->dest_pid) {
|
p->src_pid == p->dest_pid) {
|
||||||
p->fcf.panid_compression = 1;
|
p->fcf.panid_compression = 1;
|
||||||
|
|
||||||
/* compressed header, only do dest pid */
|
|
||||||
flen->src_pid_len = 0;
|
|
||||||
} else {
|
} else {
|
||||||
p->fcf.panid_compression = 0;
|
p->fcf.panid_compression = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
frame802154_has_panid(&p->fcf, &has_src_panid, &has_dest_panid);
|
||||||
|
|
||||||
|
if(has_src_panid) {
|
||||||
|
flen->src_pid_len = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(has_dest_panid) {
|
||||||
|
flen->dest_pid_len = 2;
|
||||||
|
}
|
||||||
|
|
||||||
/* determine address lengths */
|
/* determine address lengths */
|
||||||
flen->dest_addr_len = addr_len(p->fcf.dest_addr_mode & 3);
|
flen->dest_addr_len = addr_len(p->fcf.dest_addr_mode & 3);
|
||||||
|
@ -144,9 +320,16 @@ field_len(frame802154_t *p, field_length_t *flen)
|
||||||
#if LLSEC802154_SECURITY_LEVEL
|
#if LLSEC802154_SECURITY_LEVEL
|
||||||
/* Aux security header */
|
/* Aux security header */
|
||||||
if(p->fcf.security_enabled & 1) {
|
if(p->fcf.security_enabled & 1) {
|
||||||
flen->aux_sec_len = 5
|
flen->aux_sec_len = 1; /* FCF + possibly frame counter and key ID */
|
||||||
|
if(p->aux_hdr.security_control.frame_counter_suppression == 0) {
|
||||||
|
if(p->aux_hdr.security_control.frame_counter_size == 1) {
|
||||||
|
flen->aux_sec_len += 5;
|
||||||
|
} else {
|
||||||
|
flen->aux_sec_len += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
#if LLSEC802154_USES_EXPLICIT_KEYS
|
#if LLSEC802154_USES_EXPLICIT_KEYS
|
||||||
+ get_key_id_len(p->aux_hdr.security_control.key_id_mode);
|
flen->aux_sec_len += get_key_id_len(p->aux_hdr.security_control.key_id_mode);
|
||||||
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
|
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
@ -167,7 +350,7 @@ frame802154_hdrlen(frame802154_t *p)
|
||||||
{
|
{
|
||||||
field_length_t flen;
|
field_length_t flen;
|
||||||
field_len(p, &flen);
|
field_len(p, &flen);
|
||||||
return 3 + flen.dest_pid_len + flen.dest_addr_len +
|
return 2 + flen.seqno_len + flen.dest_pid_len + flen.dest_addr_len +
|
||||||
flen.src_pid_len + flen.src_addr_len + flen.aux_sec_len;
|
flen.src_pid_len + flen.src_addr_len + flen.aux_sec_len;
|
||||||
}
|
}
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
|
@ -201,13 +384,18 @@ frame802154_create(frame802154_t *p, uint8_t *buf)
|
||||||
((p->fcf.frame_pending & 1) << 4) |
|
((p->fcf.frame_pending & 1) << 4) |
|
||||||
((p->fcf.ack_required & 1) << 5) |
|
((p->fcf.ack_required & 1) << 5) |
|
||||||
((p->fcf.panid_compression & 1) << 6);
|
((p->fcf.panid_compression & 1) << 6);
|
||||||
buf[1] = ((p->fcf.dest_addr_mode & 3) << 2) |
|
buf[1] = ((p->fcf.sequence_number_suppression & 1)) |
|
||||||
|
((p->fcf.ie_list_present & 1)) << 1 |
|
||||||
|
((p->fcf.dest_addr_mode & 3) << 2) |
|
||||||
((p->fcf.frame_version & 3) << 4) |
|
((p->fcf.frame_version & 3) << 4) |
|
||||||
((p->fcf.src_addr_mode & 3) << 6);
|
((p->fcf.src_addr_mode & 3) << 6);
|
||||||
|
|
||||||
/* sequence number */
|
pos = 2;
|
||||||
buf[2] = p->seq;
|
|
||||||
pos = 3;
|
/* Sequence number */
|
||||||
|
if(flen.seqno_len == 1) {
|
||||||
|
buf[pos++] = p->seq;
|
||||||
|
}
|
||||||
|
|
||||||
/* Destination PAN ID */
|
/* Destination PAN ID */
|
||||||
if(flen.dest_pid_len == 2) {
|
if(flen.dest_pid_len == 2) {
|
||||||
|
@ -230,7 +418,6 @@ frame802154_create(frame802154_t *p, uint8_t *buf)
|
||||||
for(c = flen.src_addr_len; c > 0; c--) {
|
for(c = flen.src_addr_len; c > 0; c--) {
|
||||||
buf[pos++] = p->src_addr[c - 1];
|
buf[pos++] = p->src_addr[c - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LLSEC802154_SECURITY_LEVEL
|
#if LLSEC802154_SECURITY_LEVEL
|
||||||
/* Aux header */
|
/* Aux header */
|
||||||
if(flen.aux_sec_len) {
|
if(flen.aux_sec_len) {
|
||||||
|
@ -238,9 +425,17 @@ frame802154_create(frame802154_t *p, uint8_t *buf)
|
||||||
#if LLSEC802154_USES_EXPLICIT_KEYS
|
#if LLSEC802154_USES_EXPLICIT_KEYS
|
||||||
| (p->aux_hdr.security_control.key_id_mode << 3)
|
| (p->aux_hdr.security_control.key_id_mode << 3)
|
||||||
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
|
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
|
||||||
|
| (p->aux_hdr.security_control.frame_counter_suppression << 5)
|
||||||
|
| (p->aux_hdr.security_control.frame_counter_size << 6)
|
||||||
;
|
;
|
||||||
|
if(p->aux_hdr.security_control.frame_counter_suppression == 0) {
|
||||||
|
/* We support only 4-byte counters */
|
||||||
memcpy(buf + pos, p->aux_hdr.frame_counter.u8, 4);
|
memcpy(buf + pos, p->aux_hdr.frame_counter.u8, 4);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
|
if(p->aux_hdr.security_control.frame_counter_size == 1) {
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if LLSEC802154_USES_EXPLICIT_KEYS
|
#if LLSEC802154_USES_EXPLICIT_KEYS
|
||||||
key_id_mode = p->aux_hdr.security_control.key_id_mode;
|
key_id_mode = p->aux_hdr.security_control.key_id_mode;
|
||||||
|
@ -272,11 +467,13 @@ frame802154_parse(uint8_t *data, int len, frame802154_t *pf)
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
frame802154_fcf_t fcf;
|
frame802154_fcf_t fcf;
|
||||||
int c;
|
int c;
|
||||||
|
int has_src_panid;
|
||||||
|
int has_dest_panid;
|
||||||
#if LLSEC802154_USES_EXPLICIT_KEYS
|
#if LLSEC802154_USES_EXPLICIT_KEYS
|
||||||
uint8_t key_id_mode;
|
uint8_t key_id_mode;
|
||||||
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
|
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
|
||||||
|
|
||||||
if(len < 3) {
|
if(len < 2) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,20 +486,32 @@ frame802154_parse(uint8_t *data, int len, frame802154_t *pf)
|
||||||
fcf.ack_required = (p[0] >> 5) & 1;
|
fcf.ack_required = (p[0] >> 5) & 1;
|
||||||
fcf.panid_compression = (p[0] >> 6) & 1;
|
fcf.panid_compression = (p[0] >> 6) & 1;
|
||||||
|
|
||||||
|
fcf.sequence_number_suppression = p[1] & 1;
|
||||||
|
fcf.ie_list_present = (p[1] >> 1) & 1;
|
||||||
fcf.dest_addr_mode = (p[1] >> 2) & 3;
|
fcf.dest_addr_mode = (p[1] >> 2) & 3;
|
||||||
fcf.frame_version = (p[1] >> 4) & 3;
|
fcf.frame_version = (p[1] >> 4) & 3;
|
||||||
fcf.src_addr_mode = (p[1] >> 6) & 3;
|
fcf.src_addr_mode = (p[1] >> 6) & 3;
|
||||||
|
|
||||||
/* copy fcf and seqNum */
|
/* copy fcf and seqNum */
|
||||||
memcpy(&pf->fcf, &fcf, sizeof(frame802154_fcf_t));
|
memcpy(&pf->fcf, &fcf, sizeof(frame802154_fcf_t));
|
||||||
pf->seq = p[2];
|
p += 2; /* Skip first two bytes */
|
||||||
p += 3; /* Skip first three bytes */
|
|
||||||
|
if(fcf.sequence_number_suppression == 0) {
|
||||||
|
pf->seq = p[0];
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
frame802154_has_panid(&fcf, &has_src_panid, &has_dest_panid);
|
||||||
|
|
||||||
/* Destination address, if any */
|
/* Destination address, if any */
|
||||||
if(fcf.dest_addr_mode) {
|
if(fcf.dest_addr_mode) {
|
||||||
|
if(has_dest_panid) {
|
||||||
/* Destination PAN */
|
/* Destination PAN */
|
||||||
pf->dest_pid = p[0] + (p[1] << 8);
|
pf->dest_pid = p[0] + (p[1] << 8);
|
||||||
p += 2;
|
p += 2;
|
||||||
|
} else {
|
||||||
|
pf->dest_pid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Destination address */
|
/* Destination address */
|
||||||
/* l = addr_len(fcf.dest_addr_mode); */
|
/* l = addr_len(fcf.dest_addr_mode); */
|
||||||
|
@ -329,9 +538,12 @@ frame802154_parse(uint8_t *data, int len, frame802154_t *pf)
|
||||||
/* Source address, if any */
|
/* Source address, if any */
|
||||||
if(fcf.src_addr_mode) {
|
if(fcf.src_addr_mode) {
|
||||||
/* Source PAN */
|
/* Source PAN */
|
||||||
if(!fcf.panid_compression) {
|
if(has_src_panid) {
|
||||||
pf->src_pid = p[0] + (p[1] << 8);
|
pf->src_pid = p[0] + (p[1] << 8);
|
||||||
p += 2;
|
p += 2;
|
||||||
|
if(!has_dest_panid) {
|
||||||
|
pf->dest_pid = pf->src_pid;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
pf->src_pid = pf->dest_pid;
|
pf->src_pid = pf->dest_pid;
|
||||||
}
|
}
|
||||||
|
@ -364,10 +576,17 @@ frame802154_parse(uint8_t *data, int len, frame802154_t *pf)
|
||||||
#if LLSEC802154_USES_EXPLICIT_KEYS
|
#if LLSEC802154_USES_EXPLICIT_KEYS
|
||||||
pf->aux_hdr.security_control.key_id_mode = (p[0] >> 3) & 3;
|
pf->aux_hdr.security_control.key_id_mode = (p[0] >> 3) & 3;
|
||||||
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
|
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
|
||||||
|
pf->aux_hdr.security_control.frame_counter_suppression = p[0] >> 5;
|
||||||
|
pf->aux_hdr.security_control.frame_counter_size = p[0] >> 6;
|
||||||
p += 1;
|
p += 1;
|
||||||
|
|
||||||
|
if(pf->aux_hdr.security_control.frame_counter_suppression == 0) {
|
||||||
memcpy(pf->aux_hdr.frame_counter.u8, p, 4);
|
memcpy(pf->aux_hdr.frame_counter.u8, p, 4);
|
||||||
p += 4;
|
p += 4;
|
||||||
|
if(pf->aux_hdr.security_control.frame_counter_size == 1) {
|
||||||
|
p ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if LLSEC802154_USES_EXPLICIT_KEYS
|
#if LLSEC802154_USES_EXPLICIT_KEYS
|
||||||
key_id_mode = pf->aux_hdr.security_control.key_id_mode;
|
key_id_mode = pf->aux_hdr.security_control.key_id_mode;
|
||||||
|
|
|
@ -61,12 +61,12 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/* Includes */
|
/* Includes */
|
||||||
#ifndef FRAME_802154_H
|
#ifndef FRAME_802154_H
|
||||||
#define FRAME_802154_H
|
#define FRAME_802154_H
|
||||||
|
|
||||||
#include "contiki-conf.h"
|
#include "contiki-conf.h"
|
||||||
|
#include "net/linkaddr.h"
|
||||||
|
|
||||||
#ifdef IEEE802154_CONF_PANID
|
#ifdef IEEE802154_CONF_PANID
|
||||||
#define IEEE802154_PANID IEEE802154_CONF_PANID
|
#define IEEE802154_PANID IEEE802154_CONF_PANID
|
||||||
|
@ -74,6 +74,18 @@
|
||||||
#define IEEE802154_PANID 0xABCD
|
#define IEEE802154_PANID 0xABCD
|
||||||
#endif /* IEEE802154_CONF_PANID */
|
#endif /* IEEE802154_CONF_PANID */
|
||||||
|
|
||||||
|
#ifdef FRAME802154_CONF_VERSION
|
||||||
|
#define FRAME802154_VERSION FRAME802154_CONF_VERSION
|
||||||
|
#else /* FRAME802154_CONF_VERSION */
|
||||||
|
#define FRAME802154_VERSION FRAME802154_IEEE802154_2006
|
||||||
|
#endif /* FRAME802154_CONF_VERSION */
|
||||||
|
|
||||||
|
#ifdef FRAME802154_CONF_SUPPR_SEQNO
|
||||||
|
#define FRAME802154_SUPPR_SEQNO FRAME802154_CONF_SUPPR_SEQNO
|
||||||
|
#else /* FRAME802154_CONF_SUPPR_SEQNO */
|
||||||
|
#define FRAME802154_SUPPR_SEQNO 0
|
||||||
|
#endif /* FRAME802154_CONF_SUPPR_SEQNO */
|
||||||
|
|
||||||
/* Macros & Defines */
|
/* Macros & Defines */
|
||||||
|
|
||||||
/** \brief These are some definitions of values used in the FCF. See the 802.15.4 spec for details.
|
/** \brief These are some definitions of values used in the FCF. See the 802.15.4 spec for details.
|
||||||
|
@ -99,6 +111,7 @@
|
||||||
|
|
||||||
#define FRAME802154_IEEE802154_2003 (0x00)
|
#define FRAME802154_IEEE802154_2003 (0x00)
|
||||||
#define FRAME802154_IEEE802154_2006 (0x01)
|
#define FRAME802154_IEEE802154_2006 (0x01)
|
||||||
|
#define FRAME802154_IEEE802154E_2012 (0x02)
|
||||||
|
|
||||||
#define FRAME802154_SECURITY_LEVEL_NONE (0)
|
#define FRAME802154_SECURITY_LEVEL_NONE (0)
|
||||||
#define FRAME802154_SECURITY_LEVEL_MIC_32 (1)
|
#define FRAME802154_SECURITY_LEVEL_MIC_32 (1)
|
||||||
|
@ -136,7 +149,9 @@ typedef struct {
|
||||||
uint8_t frame_pending; /**< 1 bit. True if sender has more data to send */
|
uint8_t frame_pending; /**< 1 bit. True if sender has more data to send */
|
||||||
uint8_t ack_required; /**< 1 bit. Is an ack frame required? */
|
uint8_t ack_required; /**< 1 bit. Is an ack frame required? */
|
||||||
uint8_t panid_compression; /**< 1 bit. Is this a compressed header? */
|
uint8_t panid_compression; /**< 1 bit. Is this a compressed header? */
|
||||||
/* uint8_t reserved; */ /**< 3 bit. Unused bits */
|
/* uint8_t reserved; */ /**< 1 bit. Unused bit */
|
||||||
|
uint8_t sequence_number_suppression; /**< 1 bit. Does the header omit sequence number?, see 802.15.4e */
|
||||||
|
uint8_t ie_list_present; /**< 1 bit. Does the header contain Information Elements?, see 802.15.4e */
|
||||||
uint8_t dest_addr_mode; /**< 2 bit. Destination address mode, see 802.15.4 */
|
uint8_t dest_addr_mode; /**< 2 bit. Destination address mode, see 802.15.4 */
|
||||||
uint8_t frame_version; /**< 2 bit. 802.15.4 frame version */
|
uint8_t frame_version; /**< 2 bit. 802.15.4 frame version */
|
||||||
uint8_t src_addr_mode; /**< 2 bit. Source address mode, see 802.15.4 */
|
uint8_t src_addr_mode; /**< 2 bit. Source address mode, see 802.15.4 */
|
||||||
|
@ -146,6 +161,8 @@ typedef struct {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t security_level; /**< 3 bit. security level */
|
uint8_t security_level; /**< 3 bit. security level */
|
||||||
uint8_t key_id_mode; /**< 2 bit. Key identifier mode */
|
uint8_t key_id_mode; /**< 2 bit. Key identifier mode */
|
||||||
|
uint8_t frame_counter_suppression; /**< 1 bit. Frame counter suppression */
|
||||||
|
uint8_t frame_counter_size; /**< 1 bit. Frame counter size (0: 4 bytes, 1: 5 bytes) */
|
||||||
uint8_t reserved; /**< 3 bit. Reserved bits */
|
uint8_t reserved; /**< 3 bit. Reserved bits */
|
||||||
} frame802154_scf_t;
|
} frame802154_scf_t;
|
||||||
|
|
||||||
|
@ -193,6 +210,20 @@ int frame802154_hdrlen(frame802154_t *p);
|
||||||
int frame802154_create(frame802154_t *p, uint8_t *buf);
|
int frame802154_create(frame802154_t *p, uint8_t *buf);
|
||||||
int frame802154_parse(uint8_t *data, int length, frame802154_t *pf);
|
int frame802154_parse(uint8_t *data, int length, frame802154_t *pf);
|
||||||
|
|
||||||
|
/* Get current PAN ID */
|
||||||
|
uint16_t frame802154_get_pan_id(void);
|
||||||
|
/* Set current PAN ID */
|
||||||
|
void frame802154_set_pan_id(uint16_t pan_id);
|
||||||
|
/* Tells whether a given Frame Control Field indicates a frame with
|
||||||
|
* source PANID and/or destination PANID */
|
||||||
|
void frame802154_has_panid(frame802154_fcf_t *fcf, int *has_src_pan_id, int *has_dest_pan_id);
|
||||||
|
/* Check if the destination PAN ID, if any, matches ours */
|
||||||
|
int frame802154_check_dest_panid(frame802154_t *frame);
|
||||||
|
/* Check is the address is a broadcast address, whatever its size */
|
||||||
|
int frame802154_is_broadcast_addr(uint8_t mode, uint8_t *addr);
|
||||||
|
/* Check and extract source and destination linkaddr from frame */
|
||||||
|
int frame802154_extract_linkaddr(frame802154_t *frame, linkaddr_t *source_address, linkaddr_t *dest_address);
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
#endif /* FRAME_802154_H */
|
#endif /* FRAME_802154_H */
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
|
@ -62,30 +62,6 @@ static uint8_t mac_dsn;
|
||||||
|
|
||||||
static uint8_t initialized = 0;
|
static uint8_t initialized = 0;
|
||||||
|
|
||||||
/** \brief The 16-bit identifier of the PAN on which the device is
|
|
||||||
* sending to. If this value is 0xffff, the device is not
|
|
||||||
* associated.
|
|
||||||
*/
|
|
||||||
static const uint16_t mac_dst_pan_id = IEEE802154_PANID;
|
|
||||||
|
|
||||||
/** \brief The 16-bit identifier of the PAN on which the device is
|
|
||||||
* operating. If this value is 0xffff, the device is not
|
|
||||||
* associated.
|
|
||||||
*/
|
|
||||||
static const uint16_t mac_src_pan_id = IEEE802154_PANID;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
|
||||||
static int
|
|
||||||
is_broadcast_addr(uint8_t mode, uint8_t *addr)
|
|
||||||
{
|
|
||||||
int i = mode == FRAME802154_SHORTADDRMODE ? 2 : 8;
|
|
||||||
while(i-- > 0) {
|
|
||||||
if(addr[i] != 0xff) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static int
|
static int
|
||||||
create_frame(int type, int do_create)
|
create_frame(int type, int do_create)
|
||||||
|
@ -93,6 +69,10 @@ create_frame(int type, int do_create)
|
||||||
frame802154_t params;
|
frame802154_t params;
|
||||||
int hdr_len;
|
int hdr_len;
|
||||||
|
|
||||||
|
if(frame802154_get_pan_id() == 0xffff) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* init to zeros */
|
/* init to zeros */
|
||||||
memset(¶ms, 0, sizeof(params));
|
memset(¶ms, 0, sizeof(params));
|
||||||
|
|
||||||
|
@ -109,10 +89,14 @@ create_frame(int type, int do_create)
|
||||||
} else {
|
} else {
|
||||||
params.fcf.ack_required = packetbuf_attr(PACKETBUF_ATTR_MAC_ACK);
|
params.fcf.ack_required = packetbuf_attr(PACKETBUF_ATTR_MAC_ACK);
|
||||||
}
|
}
|
||||||
|
/* We do not compress PAN ID in outgoing frames, i.e. include one PAN ID (dest by default)
|
||||||
|
* There is one exception, seemingly a typo in Table 2a: rows 2 and 3: when there is no
|
||||||
|
* source nor destination address, we have dest PAN ID iff compression is *set*. */
|
||||||
params.fcf.panid_compression = 0;
|
params.fcf.panid_compression = 0;
|
||||||
|
params.fcf.sequence_number_suppression = FRAME802154_SUPPR_SEQNO;
|
||||||
|
|
||||||
/* Insert IEEE 802.15.4 (2006) version bits. */
|
/* Insert IEEE 802.15.4 version bits. */
|
||||||
params.fcf.frame_version = FRAME802154_IEEE802154_2006;
|
params.fcf.frame_version = FRAME802154_VERSION;
|
||||||
|
|
||||||
#if LLSEC802154_SECURITY_LEVEL
|
#if LLSEC802154_SECURITY_LEVEL
|
||||||
if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL)) {
|
if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL)) {
|
||||||
|
@ -120,8 +104,13 @@ create_frame(int type, int do_create)
|
||||||
}
|
}
|
||||||
/* Setting security-related attributes */
|
/* Setting security-related attributes */
|
||||||
params.aux_hdr.security_control.security_level = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL);
|
params.aux_hdr.security_control.security_level = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL);
|
||||||
|
#if LLSEC802154_USES_FRAME_COUNTER
|
||||||
params.aux_hdr.frame_counter.u16[0] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1);
|
params.aux_hdr.frame_counter.u16[0] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1);
|
||||||
params.aux_hdr.frame_counter.u16[1] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3);
|
params.aux_hdr.frame_counter.u16[1] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3);
|
||||||
|
#else /* LLSEC802154_USES_FRAME_COUNTER */
|
||||||
|
params.aux_hdr.security_control.frame_counter_suppression = 1;
|
||||||
|
params.aux_hdr.security_control.frame_counter_size = 1;
|
||||||
|
#endif /* LLSEC802154_USES_FRAME_COUNTER */
|
||||||
#if LLSEC802154_USES_EXPLICIT_KEYS
|
#if LLSEC802154_USES_EXPLICIT_KEYS
|
||||||
params.aux_hdr.security_control.key_id_mode = packetbuf_attr(PACKETBUF_ATTR_KEY_ID_MODE);
|
params.aux_hdr.security_control.key_id_mode = packetbuf_attr(PACKETBUF_ATTR_KEY_ID_MODE);
|
||||||
params.aux_hdr.key_index = packetbuf_attr(PACKETBUF_ATTR_KEY_INDEX);
|
params.aux_hdr.key_index = packetbuf_attr(PACKETBUF_ATTR_KEY_INDEX);
|
||||||
|
@ -157,14 +146,13 @@ create_frame(int type, int do_create)
|
||||||
} else {
|
} else {
|
||||||
params.fcf.src_addr_mode = FRAME802154_LONGADDRMODE;
|
params.fcf.src_addr_mode = FRAME802154_LONGADDRMODE;
|
||||||
}
|
}
|
||||||
params.dest_pid = mac_dst_pan_id;
|
params.dest_pid = frame802154_get_pan_id();
|
||||||
|
|
||||||
if(packetbuf_holds_broadcast()) {
|
if(packetbuf_holds_broadcast()) {
|
||||||
/* Broadcast requires short address mode. */
|
/* Broadcast requires short address mode. */
|
||||||
params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE;
|
params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE;
|
||||||
params.dest_addr[0] = 0xFF;
|
params.dest_addr[0] = 0xFF;
|
||||||
params.dest_addr[1] = 0xFF;
|
params.dest_addr[1] = 0xFF;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
linkaddr_copy((linkaddr_t *)¶ms.dest_addr,
|
linkaddr_copy((linkaddr_t *)¶ms.dest_addr,
|
||||||
packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
|
packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
|
||||||
|
@ -177,7 +165,7 @@ create_frame(int type, int do_create)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the source PAN ID to the global variable. */
|
/* Set the source PAN ID to the global variable. */
|
||||||
params.src_pid = mac_src_pan_id;
|
params.src_pid = frame802154_get_pan_id();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up the source address using only the long address mode for
|
* Set up the source address using only the long address mode for
|
||||||
|
@ -191,7 +179,6 @@ create_frame(int type, int do_create)
|
||||||
if(!do_create) {
|
if(!do_create) {
|
||||||
/* Only calculate header length */
|
/* Only calculate header length */
|
||||||
return hdr_len;
|
return hdr_len;
|
||||||
|
|
||||||
} else if(packetbuf_hdralloc(hdr_len)) {
|
} else if(packetbuf_hdralloc(hdr_len)) {
|
||||||
frame802154_create(¶ms, packetbuf_hdrptr());
|
frame802154_create(¶ms, packetbuf_hdrptr());
|
||||||
|
|
||||||
|
@ -230,19 +217,23 @@ parse(void)
|
||||||
packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, frame.fcf.frame_type);
|
packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, frame.fcf.frame_type);
|
||||||
|
|
||||||
if(frame.fcf.dest_addr_mode) {
|
if(frame.fcf.dest_addr_mode) {
|
||||||
if(frame.dest_pid != mac_src_pan_id &&
|
if(frame.dest_pid != frame802154_get_pan_id() &&
|
||||||
frame.dest_pid != FRAME802154_BROADCASTPANDID) {
|
frame.dest_pid != FRAME802154_BROADCASTPANDID) {
|
||||||
/* Packet to another PAN */
|
/* Packet to another PAN */
|
||||||
PRINTF("15.4: for another pan %u\n", frame.dest_pid);
|
PRINTF("15.4: for another pan %u\n", frame.dest_pid);
|
||||||
return FRAMER_FAILED;
|
return FRAMER_FAILED;
|
||||||
}
|
}
|
||||||
if(!is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr)) {
|
if(!frame802154_is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr)) {
|
||||||
packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, (linkaddr_t *)&frame.dest_addr);
|
packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, (linkaddr_t *)&frame.dest_addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (linkaddr_t *)&frame.src_addr);
|
packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (linkaddr_t *)&frame.src_addr);
|
||||||
packetbuf_set_attr(PACKETBUF_ATTR_PENDING, frame.fcf.frame_pending);
|
packetbuf_set_attr(PACKETBUF_ATTR_PENDING, frame.fcf.frame_pending);
|
||||||
|
if(frame.fcf.sequence_number_suppression == 0) {
|
||||||
packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, frame.seq);
|
packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, frame.seq);
|
||||||
|
} else {
|
||||||
|
packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, 0xffff);
|
||||||
|
}
|
||||||
#if NETSTACK_CONF_WITH_RIME
|
#if NETSTACK_CONF_WITH_RIME
|
||||||
packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, frame.seq);
|
packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, frame.seq);
|
||||||
#endif
|
#endif
|
||||||
|
@ -250,8 +241,10 @@ parse(void)
|
||||||
#if LLSEC802154_SECURITY_LEVEL
|
#if LLSEC802154_SECURITY_LEVEL
|
||||||
if(frame.fcf.security_enabled) {
|
if(frame.fcf.security_enabled) {
|
||||||
packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, frame.aux_hdr.security_control.security_level);
|
packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, frame.aux_hdr.security_control.security_level);
|
||||||
|
#if LLSEC802154_USES_FRAME_COUNTER
|
||||||
packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, frame.aux_hdr.frame_counter.u16[0]);
|
packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, frame.aux_hdr.frame_counter.u16[0]);
|
||||||
packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, frame.aux_hdr.frame_counter.u16[1]);
|
packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, frame.aux_hdr.frame_counter.u16[1]);
|
||||||
|
#endif /* LLSEC802154_USES_FRAME_COUNTER */
|
||||||
#if LLSEC802154_USES_EXPLICIT_KEYS
|
#if LLSEC802154_USES_EXPLICIT_KEYS
|
||||||
packetbuf_set_attr(PACKETBUF_ATTR_KEY_ID_MODE, frame.aux_hdr.security_control.key_id_mode);
|
packetbuf_set_attr(PACKETBUF_ATTR_KEY_ID_MODE, frame.aux_hdr.security_control.key_id_mode);
|
||||||
packetbuf_set_attr(PACKETBUF_ATTR_KEY_INDEX, frame.aux_hdr.key_index);
|
packetbuf_set_attr(PACKETBUF_ATTR_KEY_INDEX, frame.aux_hdr.key_index);
|
||||||
|
|
Loading…
Reference in a new issue