mbed-os/features/nanostack/sal-stack-nanostack/source/6LoWPAN/MAC/mac_ie_lib.c

213 lines
6.9 KiB
C

/*
* Copyright (c) 2018, Pelion 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 "common_functions.h"
#include "mac_common_defines.h"
#include "mac_ie_lib.h"
#define MAC_IE_HEADER_LENGTH_MASK 0x007f
#define MAC_IE_HEADER_ID_MASK 0x7f80
#define MAC_IE_PAYLOAD_LENGTH_MASK 0x07ff
#define MAC_IE_PAYLOAD_ID_MASK 0x7800
#define MAC_IE_TYPE_PAYLOAD_MASK 0x8000
#define MAC_NESTED_LONG_IE_PAYLOAD_LENGTH_MASK 0x07ff
#define MAC_NESTED_LONG_IE_PAYLOAD_ID_MASK 0x7800
#define MAC_NESTED_SHORT_IE_PAYLOAD_LENGTH_MASK 0x00ff
#define MAC_NESTED_SHORT_IE_PAYLOAD_ID_MASK 0x7f00
#define MAC_NESTED_IE_TYPE_LONG_MASK 0x8000
static void mac_ie_header_parse(mac_header_IE_t *header_element, uint8_t *ptr)
{
uint16_t ie_dummy = common_read_16_bit_inverse(ptr);
header_element->length = (ie_dummy & MAC_IE_HEADER_LENGTH_MASK);
header_element->id = ((ie_dummy & MAC_IE_HEADER_ID_MASK) >> 7);
header_element->content_ptr = ptr + 2;
}
static void mac_ie_payload_parse(mac_payload_IE_t *payload_element, uint8_t *ptr)
{
uint16_t ie_dummy = common_read_16_bit_inverse(ptr);
payload_element->length = (ie_dummy & MAC_IE_PAYLOAD_LENGTH_MASK);
payload_element->id = ((ie_dummy & MAC_IE_PAYLOAD_ID_MASK) >> 11);
payload_element->content_ptr = ptr + 2;
}
static void mac_ie_nested_id_parse(mac_nested_payload_IE_t *element, uint8_t *ptr)
{
uint16_t ie_dummy = common_read_16_bit_inverse(ptr);
if (ie_dummy & MAC_NESTED_IE_TYPE_LONG_MASK) {
element->type_long = true;
element->length = (ie_dummy & MAC_NESTED_LONG_IE_PAYLOAD_LENGTH_MASK);
element->id = ((ie_dummy & MAC_NESTED_LONG_IE_PAYLOAD_ID_MASK) >> 11);
} else {
element->type_long = false;
element->length = (ie_dummy & MAC_NESTED_SHORT_IE_PAYLOAD_LENGTH_MASK);
element->id = ((ie_dummy & MAC_NESTED_SHORT_IE_PAYLOAD_ID_MASK) >> 8);
}
element->content_ptr = ptr + 2;
}
uint8_t *mac_ie_header_base_write(uint8_t *ptr, uint8_t type, uint16_t length)
{
uint16_t ie_dummy = 0; //Header Type
ie_dummy |= (length & MAC_IE_HEADER_LENGTH_MASK);
ie_dummy |= ((type << 7) & MAC_IE_HEADER_ID_MASK);
return common_write_16_bit_inverse(ie_dummy, ptr);
}
uint8_t *mac_ie_payload_base_write(uint8_t *ptr, uint8_t type, uint16_t length)
{
uint16_t ie_dummy = MAC_IE_TYPE_PAYLOAD_MASK; //Payload type
ie_dummy |= (length & MAC_IE_PAYLOAD_LENGTH_MASK);
ie_dummy |= ((type << 11) & MAC_IE_PAYLOAD_ID_MASK);
return common_write_16_bit_inverse(ie_dummy, ptr);
}
uint8_t *mac_ie_nested_ie_long_base_write(uint8_t *ptr, uint8_t sub_id, uint16_t length)
{
uint16_t ie_dummy = MAC_NESTED_IE_TYPE_LONG_MASK;
ie_dummy |= (length & MAC_NESTED_LONG_IE_PAYLOAD_LENGTH_MASK);
ie_dummy |= ((sub_id << 11) & MAC_NESTED_LONG_IE_PAYLOAD_ID_MASK);
return common_write_16_bit_inverse(ie_dummy, ptr);
}
uint8_t *mac_ie_nested_ie_short_base_write(uint8_t *ptr, uint8_t sub_id, uint16_t length)
{
uint16_t ie_dummy = 0;
ie_dummy |= (length & MAC_NESTED_SHORT_IE_PAYLOAD_LENGTH_MASK);
ie_dummy |= ((sub_id << 8) & MAC_NESTED_SHORT_IE_PAYLOAD_ID_MASK);
return common_write_16_bit_inverse(ie_dummy, ptr);
}
uint16_t mac_ie_payload_discover(uint8_t *payload_ptr, uint16_t length, mac_payload_IE_t *payload_ie)
{
mac_payload_IE_t ie_element;
while (length >= 2) {
mac_ie_payload_parse(&ie_element, payload_ptr);
if (payload_ie->id == ie_element.id) {
payload_ie->content_ptr = ie_element.content_ptr;
payload_ie->length = ie_element.length;
return ie_element.length;
}
length -= ie_element.length + 2;
payload_ptr += ie_element.length + 2;
}
return 0;
}
uint16_t mac_ie_nested_discover(uint8_t *payload_ptr, uint16_t length, mac_nested_payload_IE_t *nested_ie)
{
mac_nested_payload_IE_t ie_element;
while (length >= 2) {
mac_ie_nested_id_parse(&ie_element, payload_ptr);
if (length < ie_element.length + 2) {
return 0;
}
if (nested_ie->id == ie_element.id && nested_ie->type_long == ie_element.type_long) {
nested_ie->content_ptr = ie_element.content_ptr;
nested_ie->length = ie_element.length;
return ie_element.length;
}
length -= ie_element.length + 2;
payload_ptr += ie_element.length + 2;
}
return 0;
}
uint16_t mac_ie_nested_tagged_discover(uint8_t *payload_ptr, uint16_t length, mac_nested_payload_IE_t *nested_ie, uint8_t sub_tag_id)
{
mac_nested_payload_IE_t ie_element;
uint8_t *sub_tag_ptr;
while (length >= 2) {
mac_ie_nested_id_parse(&ie_element, payload_ptr);
if (length < ie_element.length + 2) {
return 0;
}
sub_tag_ptr = ie_element.content_ptr;
if (ie_element.length > 1 && nested_ie->id == ie_element.id && *sub_tag_ptr == sub_tag_id) {
sub_tag_ptr++;
ie_element.length--;
nested_ie->content_ptr = sub_tag_ptr;
nested_ie->length = ie_element.length;
return ie_element.length;
}
length -= ie_element.length + 2;
payload_ptr += ie_element.length + 2;
}
return 0;
}
uint8_t mac_ie_header_discover(uint8_t *header_ptr, uint16_t length, mac_header_IE_t *header_ie)
{
mac_header_IE_t ie_element;
while (length >= 2) {
mac_ie_header_parse(&ie_element, header_ptr);
if (header_ie->id == ie_element.id) {
header_ie->content_ptr = ie_element.content_ptr;
header_ie->length = ie_element.length;
return ie_element.length;
}
length -= ie_element.length + 2;
header_ptr += ie_element.length + 2;
}
return 0;
}
uint8_t mac_ie_header_sub_id_discover(uint8_t *header_ptr, uint16_t length, mac_header_IE_t *header_ie, uint8_t sub_id)
{
mac_header_IE_t ie_element;
uint8_t *sub_id_ptr;
while (length > 2) {
mac_ie_header_parse(&ie_element, header_ptr);
sub_id_ptr = ie_element.content_ptr;
if (ie_element.length && header_ie->id == ie_element.id && *sub_id_ptr == sub_id) {
sub_id_ptr++;
ie_element.length--;
header_ie->content_ptr = sub_id_ptr;
header_ie->length = ie_element.length;
return ie_element.length;
}
length -= ie_element.length + 2;
header_ptr += ie_element.length + 2;
}
return 0;
}