mirror of https://github.com/ARMmbed/mbed-os.git
786 lines
24 KiB
C
786 lines
24 KiB
C
/*
|
|
* Copyright (c) 2016-2018, Arm Limited and affiliates.
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
#include "nsconfig.h"
|
|
#include "ns_types.h"
|
|
#include "string.h"
|
|
#include "ns_trace.h"
|
|
#include "mlme.h"
|
|
#include "mac_api.h"
|
|
#include "fhss_api.h"
|
|
#include "common_functions.h"
|
|
#include "mac_common_defines.h"
|
|
#include "MAC/IEEE802_15_4/mac_defines.h"
|
|
#include "MAC/IEEE802_15_4/mac_mcps_sap.h"
|
|
#include "MAC/IEEE802_15_4/mac_header_helper_functions.h"
|
|
#include "MAC/rf_driver_storage.h"
|
|
|
|
static uint8_t *mcps_mac_security_aux_header_start_pointer_get(const mac_pre_parsed_frame_t *buffer);
|
|
static uint8_t *mac_header_information_elements_write(const mac_pre_build_frame_t *buffer, uint8_t *ptr);
|
|
|
|
|
|
static uint8_t mac_fcf_length(const mac_fcf_sequence_t *header)
|
|
{
|
|
uint8_t length;
|
|
if (header->frameVersion == MAC_FRAME_VERSION_2015) {
|
|
if (header->sequenceNumberSuppress) {
|
|
length = 2; //Skip FCF
|
|
} else {
|
|
length = 3; //Skip FCF + DSN
|
|
}
|
|
} else {
|
|
length = 3; //Skip FCF + DSN
|
|
}
|
|
return length;
|
|
}
|
|
|
|
bool mac_dst_panid_present(const mac_fcf_sequence_t *header)
|
|
{
|
|
bool presents = false;
|
|
if (header->DstAddrMode && header->SrcAddrMode) {
|
|
if (header->frameVersion == MAC_FRAME_VERSION_2015) {
|
|
if (header->DstAddrMode == MAC_ADDR_MODE_64_BIT && header->SrcAddrMode == MAC_ADDR_MODE_64_BIT && header->intraPan) {
|
|
|
|
} else {
|
|
presents = true;
|
|
}
|
|
} else {
|
|
presents = true;
|
|
}
|
|
|
|
} else if (header->DstAddrMode && !header->SrcAddrMode) {
|
|
if (header->frameVersion == MAC_FRAME_VERSION_2015) {
|
|
if (!header->intraPan) {
|
|
presents = true;
|
|
}
|
|
} else {
|
|
presents = true;
|
|
}
|
|
|
|
} else if (!header->DstAddrMode && !header->SrcAddrMode) {
|
|
if (header->frameVersion == MAC_FRAME_VERSION_2015) {
|
|
if (header->intraPan) {
|
|
presents = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return presents;
|
|
}
|
|
|
|
bool mac_src_panid_present(const mac_fcf_sequence_t *header)
|
|
{
|
|
bool presents = false;
|
|
if (header->DstAddrMode && header->SrcAddrMode) {
|
|
if (header->frameVersion == MAC_FRAME_VERSION_2015) {
|
|
if (header->DstAddrMode == MAC_ADDR_MODE_64_BIT && header->SrcAddrMode == MAC_ADDR_MODE_64_BIT) {
|
|
|
|
} else if (!header->intraPan) {
|
|
presents = true;
|
|
}
|
|
} else if (!header->intraPan) {
|
|
presents = true;
|
|
}
|
|
|
|
} else if (header->SrcAddrMode) {
|
|
if (header->frameVersion == MAC_FRAME_VERSION_2015) {
|
|
if (!header->intraPan) {
|
|
presents = true;
|
|
}
|
|
} else {
|
|
presents = true;
|
|
}
|
|
}
|
|
return presents;
|
|
}
|
|
|
|
uint8_t mac_address_length(uint8_t address_mode)
|
|
{
|
|
uint8_t length = 0;
|
|
switch (address_mode) {
|
|
case MAC_ADDR_MODE_NONE:
|
|
break;
|
|
case MAC_ADDR_MODE_16_BIT:
|
|
length = 2;
|
|
break;
|
|
case MAC_ADDR_MODE_64_BIT:
|
|
length = 8;
|
|
break;
|
|
}
|
|
return length;
|
|
}
|
|
|
|
static uint8_t mac_dst_address_length_with_panid(const mac_fcf_sequence_t *header)
|
|
{
|
|
uint8_t length = 0;
|
|
|
|
if (header->DstPanPresents) {
|
|
length += 2;
|
|
}
|
|
|
|
length += mac_address_length(header->DstAddrMode);
|
|
|
|
return length;
|
|
}
|
|
|
|
static uint8_t mac_src_address_length_with_panid(const mac_fcf_sequence_t *header)
|
|
{
|
|
uint8_t length = 0;
|
|
|
|
if (header->SrcPanPresents) {
|
|
length += 2;
|
|
}
|
|
|
|
length += mac_address_length(header->SrcAddrMode);
|
|
|
|
return length;
|
|
}
|
|
|
|
|
|
uint8_t mac_security_mic_length_get(uint8_t security_level)
|
|
{
|
|
uint8_t mic_length;
|
|
switch (security_level) {
|
|
case 1:
|
|
case 5:
|
|
mic_length = 4;
|
|
break;
|
|
case 2:
|
|
case 6:
|
|
mic_length = 8;
|
|
break;
|
|
case 3:
|
|
case 7:
|
|
mic_length = 16;
|
|
break;
|
|
default:
|
|
mic_length = 0;
|
|
break;
|
|
}
|
|
return mic_length;
|
|
}
|
|
|
|
uint8_t mac_header_security_aux_header_length(uint8_t security_level, uint8_t keyIdmode)
|
|
{
|
|
if (security_level == 0) {
|
|
return 0;
|
|
}
|
|
uint8_t header_length = 5; //Header + 32-bit counter
|
|
switch (keyIdmode) {
|
|
case MAC_KEY_ID_MODE_SRC8_IDX:
|
|
header_length += 4; //64-bit key source first part
|
|
/* fall through */
|
|
case MAC_KEY_ID_MODE_SRC4_IDX:
|
|
header_length += 4; //32-bit key source inline
|
|
/* fall through */
|
|
case MAC_KEY_ID_MODE_IDX:
|
|
header_length += 1;
|
|
break;
|
|
default:
|
|
|
|
break;
|
|
}
|
|
return header_length;
|
|
}
|
|
|
|
uint8_t mac_header_address_length(const mac_fcf_sequence_t *fcf)
|
|
{
|
|
uint8_t address_length = 0;
|
|
|
|
address_length += mac_dst_address_length_with_panid(fcf);
|
|
address_length += mac_src_address_length_with_panid(fcf);
|
|
|
|
return address_length;
|
|
|
|
}
|
|
|
|
void mac_header_security_parameter_set(mac_aux_security_header_t *header, const mlme_security_t *frame_setup)
|
|
{
|
|
header->securityLevel = frame_setup->SecurityLevel;
|
|
|
|
if (header->securityLevel) {
|
|
uint8_t keysource_len = 0;
|
|
|
|
header->KeyIdMode = frame_setup->KeyIdMode;
|
|
switch (header->KeyIdMode) {
|
|
case MAC_KEY_ID_MODE_IMPLICIT:
|
|
//Security header + 32-bit security counter
|
|
break;
|
|
|
|
case MAC_KEY_ID_MODE_SRC8_IDX:
|
|
keysource_len += 4; //64-bit key source first part
|
|
/* fall through */
|
|
case MAC_KEY_ID_MODE_SRC4_IDX:
|
|
keysource_len += 4; //32-bit key source inline
|
|
/* fall through */
|
|
case MAC_KEY_ID_MODE_IDX:
|
|
//Security header + 32-bit security counter + Key index
|
|
header->KeyIndex = frame_setup->KeyIndex;
|
|
break;
|
|
}
|
|
if (keysource_len) {
|
|
memcpy(header->Keysource, frame_setup->Keysource, keysource_len);
|
|
}
|
|
}
|
|
}
|
|
|
|
const uint8_t *mac_header_parse_fcf_dsn(mac_fcf_sequence_t *header, const uint8_t *ptr)
|
|
{
|
|
uint16_t fcf = common_read_16_bit_inverse(ptr);
|
|
ptr += 2;
|
|
|
|
//Read Frame Type
|
|
header->frametype = ((fcf & MAC_FCF_FRAME_TYPE_MASK) >> MAC_FCF_FRAME_TYPE_SHIFT);
|
|
header->securityEnabled = ((fcf & MAC_FCF_SECURITY_BIT_MASK) >> MAC_FCF_SECURITY_BIT_SHIFT);
|
|
header->framePending = ((fcf & MAC_FCF_PENDING_BIT_MASK) >> MAC_FCF_PENDING_BIT_SHIFT);
|
|
header->ackRequested = ((fcf & MAC_FCF_ACK_REQ_BIT_MASK) >> MAC_FCF_ACK_REQ_BIT_SHIFT);
|
|
header->intraPan = ((fcf & MAC_FCF_INTRA_PANID_MASK) >> MAC_FCF_INTRA_PANID_SHIFT);
|
|
|
|
header->DstAddrMode = ((fcf & MAC_FCF_DST_ADDR_MASK) >> MAC_FCF_DST_ADDR_SHIFT);
|
|
header->frameVersion = ((fcf & MAC_FCF_VERSION_MASK) >> MAC_FCF_VERSION_SHIFT);
|
|
header->SrcAddrMode = ((fcf & MAC_FCF_SRC_ADDR_MASK) >> MAC_FCF_SRC_ADDR_SHIFT);
|
|
|
|
if (header->frameVersion == MAC_FRAME_VERSION_2015) {
|
|
header->sequenceNumberSuppress = ((fcf & MAC_FCF_SEQ_NUM_SUPPRESS_MASK) >> MAC_FCF_SEQ_NUM_SUPPRESS_SHIFT);
|
|
header->informationElementsPresets = ((fcf & MAC_FCF_IE_PRESENTS_MASK) >> MAC_FCF_IE_PRESENTS_SHIFT);
|
|
} else {
|
|
//SET False to ALL 2015 Extension's by default
|
|
header->sequenceNumberSuppress = false;
|
|
header->informationElementsPresets = false;
|
|
}
|
|
|
|
if (header->frameVersion < MAC_FRAME_VERSION_2015 || (header->frameVersion == MAC_FRAME_VERSION_2015 && !header->sequenceNumberSuppress)) {
|
|
header->DSN = *ptr++;
|
|
} else {
|
|
header->DSN = 0;
|
|
}
|
|
//Check PanID presents at header
|
|
header->DstPanPresents = mac_dst_panid_present(header);
|
|
header->SrcPanPresents = mac_src_panid_present(header);
|
|
return ptr;
|
|
|
|
}
|
|
|
|
static uint8_t *mac_header_write_fcf_dsn(const mac_fcf_sequence_t *header, uint8_t *ptr)
|
|
{
|
|
uint16_t fcf = 0;
|
|
//Read Frame Type
|
|
fcf |= (header->frametype << MAC_FCF_FRAME_TYPE_SHIFT);
|
|
fcf |= (header->securityEnabled << MAC_FCF_SECURITY_BIT_SHIFT);
|
|
fcf |= (header->framePending << MAC_FCF_PENDING_BIT_SHIFT);
|
|
fcf |= (header->ackRequested << MAC_FCF_ACK_REQ_BIT_SHIFT);
|
|
fcf |= (header->intraPan << MAC_FCF_INTRA_PANID_SHIFT);
|
|
fcf |= (header->sequenceNumberSuppress << MAC_FCF_SEQ_NUM_SUPPRESS_SHIFT);
|
|
fcf |= (header->informationElementsPresets << MAC_FCF_IE_PRESENTS_SHIFT);
|
|
fcf |= (header->DstAddrMode << MAC_FCF_DST_ADDR_SHIFT);
|
|
fcf |= (header->frameVersion << MAC_FCF_VERSION_SHIFT);
|
|
fcf |= (header->SrcAddrMode << MAC_FCF_SRC_ADDR_SHIFT);
|
|
ptr = common_write_16_bit_inverse(fcf, ptr);
|
|
if (header->frameVersion < MAC_FRAME_VERSION_2015 || (header->frameVersion == MAC_FRAME_VERSION_2015 && !header->sequenceNumberSuppress)) {
|
|
*ptr++ = header->DSN;
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
uint16_t mac_header_off_set_to_aux_header(const mac_fcf_sequence_t *fcf)
|
|
{
|
|
//Skip first FCF & address field
|
|
uint16_t offset = mac_fcf_length(fcf);//Skip FCF + DSN
|
|
offset += mac_dst_address_length_with_panid(fcf);
|
|
offset += mac_address_length(fcf->SrcAddrMode);
|
|
if (fcf->SrcPanPresents) {
|
|
offset += 2; //Skip PanId
|
|
}
|
|
return offset;
|
|
}
|
|
|
|
void mac_header_security_aux_header_parse(const uint8_t *ptr, mlme_security_t *security_params)
|
|
{
|
|
uint8_t key_source_len = 0;
|
|
security_params->KeyIdMode = (*ptr >> 3);
|
|
security_params->SecurityLevel = *ptr++;
|
|
ptr += 4; //Skip Frame counter
|
|
switch (security_params->KeyIdMode) {
|
|
case MAC_KEY_ID_MODE_IMPLICIT:
|
|
break;
|
|
case MAC_KEY_ID_MODE_SRC8_IDX:
|
|
key_source_len += 4;
|
|
/* fall through */
|
|
case MAC_KEY_ID_MODE_SRC4_IDX:
|
|
key_source_len += 4;
|
|
memcpy(security_params->Keysource, ptr, key_source_len);
|
|
ptr += key_source_len;
|
|
/* fall through */
|
|
case MAC_KEY_ID_MODE_IDX:
|
|
security_params->KeyIndex = *ptr;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void mac_header_security_components_read(mac_pre_parsed_frame_t *buffer, mlme_security_t *security_params)
|
|
{
|
|
memset(security_params, 0, sizeof(mlme_security_t));
|
|
if (!buffer->fcf_dsn.securityEnabled) {
|
|
return;
|
|
}
|
|
|
|
mac_header_security_aux_header_parse(mcps_mac_security_aux_header_start_pointer_get(buffer), security_params);
|
|
|
|
}
|
|
|
|
static bool mac_header_pan_full_compressed(const mac_fcf_sequence_t *header)
|
|
{
|
|
if (header->frameVersion == MAC_FRAME_VERSION_2015 && (!header->DstPanPresents && !header->SrcPanPresents) && header->intraPan) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static uint16_t mac_header_read_src_pan(const mac_fcf_sequence_t *header, const uint8_t *ptr)
|
|
{
|
|
ptr += mac_fcf_length(header);//Skip FCF + DSN
|
|
|
|
ptr += mac_dst_address_length_with_panid(header); //Skip Dst panID & Address
|
|
|
|
return common_read_16_bit_inverse(ptr);
|
|
}
|
|
|
|
static uint16_t mac_header_read_dst_pan(const mac_fcf_sequence_t *header, const uint8_t *ptr)
|
|
{
|
|
ptr += mac_fcf_length(header);//Skip FCF + DSN
|
|
|
|
return common_read_16_bit_inverse(ptr);
|
|
}
|
|
|
|
uint16_t mac_header_get_src_panid(const mac_fcf_sequence_t *header, const uint8_t *ptr, uint16_t configured_pan_id)
|
|
{
|
|
if (mac_header_pan_full_compressed(header)) {
|
|
return configured_pan_id;
|
|
}
|
|
|
|
if (!header->SrcPanPresents) {
|
|
if (!header->DstPanPresents) {
|
|
return 0xffff;
|
|
}
|
|
return mac_header_read_dst_pan(header, ptr);
|
|
}
|
|
|
|
return mac_header_read_src_pan(header, ptr);
|
|
}
|
|
|
|
uint16_t mac_header_get_dst_panid(const mac_fcf_sequence_t *header, const uint8_t *ptr, uint16_t configured_pan_id)
|
|
{
|
|
if (mac_header_pan_full_compressed(header)) {
|
|
return configured_pan_id;
|
|
}
|
|
if (!header->DstPanPresents) {
|
|
if (header->SrcPanPresents && header->frameVersion == MAC_FRAME_VERSION_2015 && header->DstAddrMode == MAC_ADDR_MODE_NONE) {
|
|
return mac_header_read_src_pan(header, ptr);
|
|
}
|
|
return 0xffff;
|
|
}
|
|
|
|
return mac_header_read_dst_pan(header, ptr);
|
|
}
|
|
|
|
void mac_header_get_src_address(const mac_fcf_sequence_t *header, const uint8_t *ptr, uint8_t *address_ptr)
|
|
{
|
|
|
|
if (header->SrcAddrMode == MAC_ADDR_MODE_NONE) {
|
|
return;
|
|
}
|
|
|
|
ptr += mac_fcf_length(header);//Skip FCF + DSN
|
|
|
|
ptr += mac_dst_address_length_with_panid(header);
|
|
|
|
uint8_t address_len, address_index, i;
|
|
|
|
address_len = mac_address_length(header->SrcAddrMode);
|
|
|
|
if (header->SrcPanPresents) {
|
|
ptr += 2; //Skip PanId
|
|
}
|
|
address_index = address_len - 1;
|
|
|
|
|
|
for (i = 0; i < address_len; i++) {
|
|
address_ptr[address_index - i] = *ptr++;
|
|
}
|
|
}
|
|
|
|
void mac_header_get_dst_address(const mac_fcf_sequence_t *header, const uint8_t *ptr, uint8_t *address_ptr)
|
|
{
|
|
|
|
if (header->DstAddrMode == MAC_ADDR_MODE_NONE) {
|
|
return;
|
|
}
|
|
uint8_t address_len, address_index, i;
|
|
|
|
ptr += mac_fcf_length(header);//Skip FCF + DSN
|
|
|
|
address_len = mac_address_length(header->DstAddrMode);
|
|
|
|
if (header->DstPanPresents) {
|
|
ptr += 2; //Skip PanId
|
|
}
|
|
address_index = address_len - 1;
|
|
|
|
for (i = 0; i < address_len; i++) {
|
|
address_ptr[address_index - i] = *ptr++;
|
|
}
|
|
}
|
|
|
|
static uint16_t mac_payload_length_calc_with_ie(uint16_t payload_length, uint16_t payload_ie_length)
|
|
{
|
|
uint16_t length = payload_length;
|
|
if (payload_ie_length) {
|
|
if (length) {
|
|
length += 2;
|
|
}
|
|
length += payload_ie_length;
|
|
}
|
|
return length;
|
|
}
|
|
|
|
uint8_t mcps_mac_header_length_from_received_frame(const mac_pre_parsed_frame_t *buffer)
|
|
{
|
|
return (buffer->mac_header_length + buffer->security_aux_header_length + buffer->header_ie_length);
|
|
}
|
|
|
|
uint8_t *mcps_mac_payload_pointer_get(const mac_pre_parsed_frame_t *buffer)
|
|
{
|
|
uint8_t *ptr = (uint8_t *) mac_header_message_start_pointer(buffer);
|
|
ptr += mcps_mac_header_length_from_received_frame(buffer);
|
|
return ptr;
|
|
}
|
|
|
|
uint8_t *mcps_security_mic_pointer_get(const mac_pre_parsed_frame_t *buffer)
|
|
{
|
|
uint8_t *ptr = mcps_mac_payload_pointer_get(buffer) + buffer->mac_payload_length;
|
|
return ptr;
|
|
}
|
|
|
|
static uint8_t *mcps_mac_security_aux_header_start_pointer_get(const mac_pre_parsed_frame_t *buffer)
|
|
{
|
|
if (!buffer->fcf_dsn.securityEnabled) {
|
|
return NULL;
|
|
}
|
|
return (uint8_t *)(mac_header_message_start_pointer(buffer) + buffer->mac_header_length);
|
|
}
|
|
|
|
uint8_t mcps_mac_command_frame_id_get(const mac_pre_parsed_frame_t *buffer)
|
|
{
|
|
const uint8_t *ptr = mcps_mac_payload_pointer_get(buffer);
|
|
return *ptr;
|
|
}
|
|
|
|
uint32_t mcps_mac_security_frame_counter_read(const mac_pre_parsed_frame_t *buffer)
|
|
{
|
|
if (!buffer->fcf_dsn.securityEnabled) {
|
|
return 0xffffffff;
|
|
}
|
|
|
|
const uint8_t *ptr = (mac_header_message_start_pointer(buffer) + buffer->mac_header_length + 1);
|
|
return common_read_32_bit_inverse(ptr);
|
|
|
|
}
|
|
|
|
static uint8_t *mcps_mac_frame_address_write(uint8_t *ptr, uint8_t addressType, const uint8_t *addressPtr)
|
|
{
|
|
if (addressType == MAC_ADDR_MODE_16_BIT) {
|
|
uint16_t tempMac16 = common_read_16_bit(addressPtr);
|
|
ptr = common_write_16_bit_inverse(tempMac16, ptr);
|
|
} else if (addressType == MAC_ADDR_MODE_64_BIT) {
|
|
uint8_t i;
|
|
for (i = 0; i < 8; i++) {
|
|
*ptr++ = addressPtr[7 - i];
|
|
}
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
static uint8_t *mac_security_interface_aux_security_header_write(uint8_t *ptr, const mac_aux_security_header_t *auxHeader)
|
|
{
|
|
uint8_t auxBaseHeader;
|
|
auxBaseHeader = auxHeader->securityLevel;
|
|
auxBaseHeader |= (auxHeader->KeyIdMode << 3);
|
|
*ptr++ = auxBaseHeader;
|
|
ptr = common_write_32_bit_inverse(auxHeader->frameCounter, ptr);
|
|
|
|
switch (auxHeader->KeyIdMode) {
|
|
case MAC_KEY_ID_MODE_SRC8_IDX:
|
|
memcpy(ptr, auxHeader->Keysource, 8);
|
|
ptr += 8;
|
|
*ptr++ = auxHeader->KeyIndex;
|
|
break;
|
|
case MAC_KEY_ID_MODE_SRC4_IDX:
|
|
memcpy(ptr, auxHeader->Keysource, 4);
|
|
ptr += 4;
|
|
*ptr++ = auxHeader->KeyIndex;
|
|
break;
|
|
case MAC_KEY_ID_MODE_IDX:
|
|
*ptr++ = auxHeader->KeyIndex;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
uint8_t *mac_generic_packet_write(struct protocol_interface_rf_mac_setup *rf_ptr, uint8_t *ptr, const mac_pre_build_frame_t *buffer)
|
|
{
|
|
ptr = mac_header_write_fcf_dsn(&buffer->fcf_dsn, ptr);
|
|
|
|
if (buffer->fcf_dsn.DstPanPresents) {
|
|
ptr = common_write_16_bit_inverse(buffer->DstPANId, ptr);
|
|
}
|
|
|
|
if (buffer->fcf_dsn.DstAddrMode) {
|
|
//Write DST
|
|
ptr = mcps_mac_frame_address_write(ptr, buffer->fcf_dsn.DstAddrMode, buffer->DstAddr);
|
|
}
|
|
|
|
if (buffer->fcf_dsn.SrcPanPresents) {
|
|
ptr = common_write_16_bit_inverse(buffer->SrcPANId, ptr);
|
|
}
|
|
|
|
if (buffer->fcf_dsn.SrcAddrMode) {
|
|
ptr = mcps_mac_frame_address_write(ptr, buffer->fcf_dsn.SrcAddrMode, buffer->SrcAddr);
|
|
}
|
|
|
|
if (buffer->fcf_dsn.securityEnabled) {
|
|
ptr = mac_security_interface_aux_security_header_write(ptr, &buffer->aux_header);
|
|
}
|
|
uint8_t *ie_start = ptr;
|
|
//Copy Payload and set IE Elemets
|
|
ptr = mac_header_information_elements_write(buffer, ptr);
|
|
if (buffer->mac_payload_length) {
|
|
memcpy(ptr, buffer->mac_payload, buffer->mac_payload_length);
|
|
ptr += buffer->mac_payload_length;
|
|
}
|
|
if (rf_ptr->fhss_api) {
|
|
if (buffer->fcf_dsn.frametype == FC_BEACON_FRAME) {
|
|
dev_driver_tx_buffer_s *tx_buf = &rf_ptr->dev_driver_tx_buffer;
|
|
uint8_t *synch_info = tx_buf->buf + rf_ptr->dev_driver->phy_driver->phy_header_length + tx_buf->len - FHSS_SYNCH_INFO_LENGTH;
|
|
rf_ptr->fhss_api->write_synch_info(rf_ptr->fhss_api, synch_info, FHSS_SYNCH_INFO_LENGTH, FHSS_SYNCH_FRAME, buffer->tx_time);
|
|
} else {
|
|
rf_ptr->fhss_api->write_synch_info(rf_ptr->fhss_api, ie_start, buffer->headerIeLength, FHSS_DATA_FRAME, buffer->tx_time);
|
|
}
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
static uint8_t *mac_write_ie_vector_list(ns_ie_iovec_t *list, uint16_t length, uint8_t *ptr)
|
|
{
|
|
const ns_ie_iovec_t *msg_iov = list;
|
|
for (uint_fast16_t i = 0; i < length; i++, msg_iov++) {
|
|
memcpy(ptr, msg_iov->ieBase, msg_iov->iovLen);
|
|
ptr += msg_iov->iovLen;
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
static bool mac_parse_header_ie(mac_header_IE_t *header_element, uint8_t *ptr)
|
|
{
|
|
uint16_t ie_dummy = common_read_16_bit_inverse(ptr);
|
|
if (ie_dummy & 0x8000) {
|
|
return false;
|
|
}
|
|
header_element->length = (ie_dummy & 0x007f);
|
|
header_element->id = ((ie_dummy & 0x7f80) >> 7);
|
|
header_element->content_ptr = ptr + 2;
|
|
return true;
|
|
}
|
|
|
|
static bool mac_parse_payload_ie(mac_payload_IE_t *payload_element, uint8_t *ptr)
|
|
{
|
|
uint16_t ie_dummy = common_read_16_bit_inverse(ptr);
|
|
if (!(ie_dummy & 0x8000)) {
|
|
return false;
|
|
}
|
|
payload_element->length = (ie_dummy & 0x07ff);
|
|
payload_element->id = ((ie_dummy & 0x7800) >> 11);
|
|
payload_element->content_ptr = ptr + 2;
|
|
return true;
|
|
}
|
|
|
|
|
|
bool mac_header_information_elements_parse(mac_pre_parsed_frame_t *buffer)
|
|
{
|
|
uint8_t *ptr = (mac_header_message_start_pointer(buffer) + buffer->mac_header_length + buffer->security_aux_header_length);
|
|
|
|
buffer->headerIePtr = NULL;
|
|
buffer->headerIeLength = 0;
|
|
buffer->payloadsIePtr = NULL;
|
|
buffer->payloadsIeLength = 0;
|
|
buffer->header_ie_length = 0;
|
|
if (!buffer->fcf_dsn.informationElementsPresets) {
|
|
buffer->macPayloadPtr = ptr;
|
|
return true;
|
|
}
|
|
|
|
if (buffer->mac_payload_length < 2) {
|
|
return false;
|
|
}
|
|
|
|
mac_header_IE_t header_ie;
|
|
buffer->headerIePtr = ptr;
|
|
|
|
while (buffer->mac_payload_length >= 2) {
|
|
|
|
if (!mac_parse_header_ie(&header_ie, ptr)) {
|
|
return false;
|
|
}
|
|
|
|
buffer->mac_payload_length -= 2;
|
|
if (header_ie.length > buffer->mac_payload_length) {
|
|
return false;
|
|
}
|
|
|
|
buffer->mac_payload_length -= header_ie.length;
|
|
|
|
buffer->header_ie_length += header_ie.length + 2;
|
|
ptr += (2 + header_ie.length);
|
|
|
|
if (header_ie.id == MAC_HEADER_TERMINATION1_IE_ID) {
|
|
break;
|
|
} else if (header_ie.id == MAC_HEADER_TERMINATION2_IE_ID) {
|
|
buffer->macPayloadPtr = ptr;
|
|
return true;
|
|
}
|
|
buffer->headerIeLength += header_ie.length + 2;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool mac_payload_information_elements_parse(mac_pre_parsed_frame_t *buffer)
|
|
{
|
|
uint8_t *ptr = (mac_header_message_start_pointer(buffer) + buffer->mac_header_length + buffer->security_aux_header_length + buffer->header_ie_length);
|
|
if (!buffer->fcf_dsn.informationElementsPresets) {
|
|
return true;
|
|
}
|
|
|
|
if (buffer->mac_payload_length < 2) {
|
|
return false;
|
|
}
|
|
|
|
//Parse Payload IE
|
|
buffer->payloadsIePtr = ptr;
|
|
mac_payload_IE_t payload_ie;
|
|
while (buffer->mac_payload_length >= 2) {
|
|
|
|
if (!mac_parse_payload_ie(&payload_ie, ptr)) {
|
|
return false;
|
|
}
|
|
buffer->mac_payload_length -= 2;
|
|
if (payload_ie.length > buffer->mac_payload_length) {
|
|
return false;
|
|
}
|
|
buffer->mac_payload_length -= payload_ie.length;
|
|
|
|
if (payload_ie.id == MAC_PAYLOAD_TERMINATION_IE_GROUP_ID) {
|
|
break;
|
|
}
|
|
buffer->payloadsIeLength += payload_ie.length + 2;
|
|
buffer->macPayloadPtr += payload_ie.length + 2;
|
|
ptr += (2 + payload_ie.length);
|
|
|
|
}
|
|
buffer->macPayloadPtr = ptr;
|
|
return true;
|
|
}
|
|
|
|
|
|
static uint8_t *mac_header_ie_terimate(uint8_t *ptr, uint8_t type)
|
|
{
|
|
uint16_t ie_dummy = 0;
|
|
ie_dummy |= (type << 7);
|
|
return common_write_16_bit_inverse(ie_dummy, ptr);
|
|
|
|
|
|
}
|
|
|
|
static uint8_t *mac_payload_ie_terimate(uint8_t *ptr)
|
|
{
|
|
uint16_t ie_dummy = 0;
|
|
ie_dummy |= (MAC_PAYLOAD_TERMINATION_IE_GROUP_ID << 11);
|
|
ie_dummy |= (1 << 15);
|
|
return common_write_16_bit_inverse(ie_dummy, ptr);
|
|
}
|
|
|
|
|
|
void mac_header_information_elements_preparation(mac_pre_build_frame_t *buffer)
|
|
{
|
|
if (buffer->message_builded) {
|
|
return;
|
|
}
|
|
|
|
if (buffer->headerIeLength || buffer->payloadsIeLength) {
|
|
buffer->fcf_dsn.frameVersion = MAC_FRAME_VERSION_2015;
|
|
buffer->fcf_dsn.informationElementsPresets = true;
|
|
buffer->message_builded = true;
|
|
//Write Header elements
|
|
if (buffer->headerIeLength) {
|
|
buffer->mac_header_length_with_security += buffer->headerIeLength;
|
|
if (!buffer->payloadsIeLength && !buffer->mac_payload_length) {
|
|
//No termination needed
|
|
return;
|
|
}
|
|
//Terminate
|
|
buffer->mac_header_length_with_security += 2;
|
|
} else {
|
|
buffer->mac_header_length_with_security += 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
uint16_t mac_buffer_total_payload_length(mac_pre_build_frame_t *buffer)
|
|
{
|
|
return mac_payload_length_calc_with_ie(buffer->mac_payload_length, buffer->payloadsIeLength);
|
|
}
|
|
|
|
|
|
static uint8_t *mac_header_information_elements_write(const mac_pre_build_frame_t *buffer, uint8_t *ptr)
|
|
{
|
|
if (buffer->fcf_dsn.frameVersion == MAC_FRAME_VERSION_2015 && buffer->fcf_dsn.informationElementsPresets) {
|
|
//Write Header elements
|
|
if (buffer->headerIeLength) {
|
|
ptr = mac_write_ie_vector_list(buffer->ie_elements.headerIeVectorList, buffer->ie_elements.headerIovLength, ptr);
|
|
|
|
if (!buffer->payloadsIeLength && !buffer->mac_payload_length) {
|
|
//No termination needed
|
|
return ptr;
|
|
} else if (!buffer->payloadsIeLength && buffer->mac_payload_length) {
|
|
return mac_header_ie_terimate(ptr, MAC_HEADER_TERMINATION2_IE_ID);
|
|
}
|
|
}
|
|
//Add Header Termination
|
|
ptr = mac_header_ie_terimate(ptr, MAC_HEADER_TERMINATION1_IE_ID);
|
|
|
|
if (buffer->payloadsIeLength) {
|
|
ptr = mac_write_ie_vector_list(buffer->ie_elements.payloadIeVectorList, buffer->ie_elements.payloadIovLength, ptr);
|
|
if (buffer->mac_payload_length) {
|
|
ptr = mac_payload_ie_terimate(ptr);
|
|
}
|
|
}
|
|
}
|
|
return ptr;
|
|
}
|
|
|