mirror of https://github.com/ARMmbed/mbed-os.git
267 lines
7.4 KiB
C
267 lines
7.4 KiB
C
/*
|
|
* Copyright (c) 2013-2019, 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 <stdint.h>
|
|
#include "string.h"
|
|
#include "nsdynmemLIB.h"
|
|
#include "ns_list.h"
|
|
#include "Common_Protocols/icmpv6.h"
|
|
#include "Service_Libs/whiteboard/whiteboard.h"
|
|
#include "platform/os_whiteboard.h"
|
|
|
|
#ifdef WHITEBOARD
|
|
static uint16_t whiteboard_device_limit = 0;
|
|
static uint16_t whiteboard_size = 0;
|
|
|
|
/* Separate internal version to avoid exporting ns_list.h unnecessarily */
|
|
typedef struct whiteboard_entry_int_t {
|
|
whiteboard_entry_t entry;
|
|
ns_list_link_t link;
|
|
} whiteboard_entry_int_t;
|
|
|
|
static NS_LIST_DEFINE(whiteboard_info, whiteboard_entry_int_t, link);
|
|
static NS_LIST_DEFINE(whiteboard_interface_list, whiteboard_entry_int_t, link);
|
|
|
|
static void whiteboard_remove_entry(whiteboard_entry_int_t *entry);
|
|
|
|
static void whiteboard_remove_entry(whiteboard_entry_int_t *entry)
|
|
{
|
|
ns_list_remove(&whiteboard_info, entry);
|
|
ns_dyn_mem_free(entry);
|
|
whiteboard_size--;
|
|
}
|
|
|
|
void whiteboard_init(int8_t id)
|
|
{
|
|
ns_list_foreach_safe(whiteboard_entry_int_t, cur, &whiteboard_info) {
|
|
if (cur->entry.interface_index == id) {
|
|
whiteboard_remove_entry(cur);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void whiteboard_init_by_prefix(int8_t id, const uint8_t address[static 8])
|
|
{
|
|
ns_list_foreach_safe(whiteboard_entry_int_t, cur, &whiteboard_info) {
|
|
if (cur->entry.interface_index == id) {
|
|
if (memcmp(cur->entry.address, address, 8) == 0) {
|
|
whiteboard_remove_entry(cur);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void whiteboard_rm_entry(int8_t id, const uint8_t address[static 16])
|
|
{
|
|
ns_list_foreach_safe(whiteboard_entry_int_t, cur, &whiteboard_info) {
|
|
if (cur->entry.interface_index == id) {
|
|
if (memcmp(cur->entry.address, address, 16) == 0) {
|
|
|
|
whiteboard_remove_entry(cur);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
whiteboard_entry_t *whiteboard_table_check_address(const uint8_t address[static 16])
|
|
{
|
|
ns_list_foreach(whiteboard_entry_int_t, cur, &whiteboard_info) {
|
|
if (memcmp(cur->entry.address, address, 16) == 0) {
|
|
return &cur->entry;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
whiteboard_entry_t *whiteboard_get(whiteboard_entry_t *cur)
|
|
{
|
|
whiteboard_entry_int_t *entry = (whiteboard_entry_int_t *) cur;
|
|
if (entry) {
|
|
entry = ns_list_get_next(&whiteboard_info, entry);
|
|
} else {
|
|
entry = ns_list_get_first(&whiteboard_info);
|
|
}
|
|
|
|
if (entry) {
|
|
return &entry->entry;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
void whiteboard_set_device_hard_limit(uint16_t limit)
|
|
{
|
|
whiteboard_device_limit = limit;
|
|
}
|
|
|
|
uint16_t whiteboard_size_get(void)
|
|
{
|
|
return whiteboard_size;
|
|
}
|
|
|
|
// XXX what is this doing? I believe it only returns entries that do NOT
|
|
// appear to be based on the EUI-64 (with a sloppy check). So given entries:
|
|
//
|
|
// 2002:db8::2345:2345:2345:2345 03:45:23:45:23:45:23:45
|
|
// 2002:db8::1 03:45:23:45:23:45:23:45
|
|
//
|
|
// it returns the 2002:db8::1 entry, not the EUI-64-based one.
|
|
//
|
|
// But why?
|
|
static whiteboard_entry_t *whiteboard_table_check_eui64(const uint8_t eui64[static 8])
|
|
{
|
|
ns_list_foreach(whiteboard_entry_int_t, cur, &whiteboard_info) {
|
|
/*Compare latter 7 bytes and eui64*/
|
|
if (memcmp(cur->entry.address + 9, eui64 + 1, 7) != 0) {
|
|
if (memcmp(cur->entry.eui64, eui64, 8) == 0) {
|
|
return &cur->entry;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
int8_t whiteboard_interface_register(const uint8_t address[static 16], int8_t nwk_id)
|
|
{
|
|
ns_list_foreach(whiteboard_entry_int_t, cur, &whiteboard_interface_list) {
|
|
if (memcmp(cur->entry.address, address, 16) == 0) {
|
|
if (cur->entry.interface_index != nwk_id) {
|
|
return -2;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
whiteboard_entry_int_t *new = ns_dyn_mem_alloc(sizeof(whiteboard_entry_int_t));
|
|
if (!new) {
|
|
return -1;
|
|
}
|
|
memcpy(new->entry.address, address, 16);
|
|
new->entry.interface_index = nwk_id;
|
|
whiteboard_os_modify(address, ADD);
|
|
ns_list_add_to_start(&whiteboard_interface_list, new);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int8_t whiteboard_interface_unregister_all_address(int8_t nwk_id)
|
|
{
|
|
ns_list_foreach_safe(whiteboard_entry_int_t, cur, &whiteboard_interface_list) {
|
|
if (cur->entry.interface_index == nwk_id) {
|
|
whiteboard_os_modify(cur->entry.address, REMOVE);
|
|
whiteboard_remove_entry(cur);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool whiteboard_interface_address_cmp(const uint8_t address[static 16])
|
|
{
|
|
ns_list_foreach(whiteboard_entry_int_t, cur, &whiteboard_interface_list) {
|
|
if (memcmp(cur->entry.address, address, 16) == 0) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
whiteboard_entry_t *whiteboard_table_update(const uint8_t address[static 16], const uint8_t eui64[static 8], uint8_t *status)
|
|
{
|
|
whiteboard_entry_t *ret_val = 0;
|
|
if (ns_list_is_empty(&whiteboard_interface_list)) {
|
|
return 0;
|
|
}
|
|
|
|
if (whiteboard_interface_address_cmp(address)) {
|
|
*status = ARO_DUPLICATE;
|
|
return 0;
|
|
}
|
|
|
|
ret_val = whiteboard_table_check_address(address);
|
|
if (ret_val) {
|
|
if (memcmp(ret_val->eui64, eui64, 8) == 0) {
|
|
*status = ARO_SUCCESS;
|
|
} else {
|
|
*status = ARO_DUPLICATE;
|
|
return 0;
|
|
}
|
|
} else {
|
|
/*Compare latter 7 bytes and eui64 (XXX why?) */
|
|
if (memcmp((address + 9), (eui64 + 1), 7) != 0) {
|
|
ret_val = whiteboard_table_check_eui64(eui64);
|
|
if (ret_val) {
|
|
memcpy(ret_val->address, address, 16);
|
|
*status = ARO_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
|
|
//allocate new
|
|
if (ret_val == 0) {
|
|
/* Check Limiter */
|
|
if (whiteboard_device_limit && whiteboard_size == whiteboard_device_limit) {
|
|
*status = ARO_FULL;
|
|
return 0;
|
|
}
|
|
|
|
whiteboard_entry_int_t *new = ns_dyn_mem_alloc(sizeof(whiteboard_entry_int_t));
|
|
if (new) {
|
|
ns_list_add_to_start(&whiteboard_info, new);
|
|
ret_val = &new->entry;
|
|
whiteboard_os_modify(address, ADD);
|
|
memcpy(ret_val->address, address, 16);
|
|
memcpy(ret_val->eui64, eui64, 8);
|
|
*status = ARO_SUCCESS;
|
|
whiteboard_size++;
|
|
} else {
|
|
*status = ARO_FULL;
|
|
}
|
|
}
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
void whiteboard_ttl_update(uint16_t ttl_time)
|
|
{
|
|
ns_list_foreach_safe(whiteboard_entry_int_t, cur, &whiteboard_info) {
|
|
if (cur->entry.ttl > ttl_time) {
|
|
cur->entry.ttl -= ttl_time;
|
|
} else {
|
|
whiteboard_os_modify(cur->entry.address, REMOVE);
|
|
whiteboard_remove_entry(cur);
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
|
|
void whiteboard_set_device_hard_limit(uint16_t limit)
|
|
{
|
|
(void)limit;
|
|
}
|
|
|
|
whiteboard_entry_t *whiteboard_get(whiteboard_entry_t *cur)
|
|
{
|
|
(void)cur;
|
|
return NULL;
|
|
}
|
|
|
|
#endif
|