mirror of https://github.com/ARMmbed/mbed-os.git
316 lines
9.5 KiB
C
316 lines
9.5 KiB
C
/*
|
|
* Copyright (c) 2018-2019, 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 <string.h>
|
|
#include "ns_types.h"
|
|
#include "ns_list.h"
|
|
#include "ns_trace.h"
|
|
#include "nsdynmemLIB.h"
|
|
#include "fhss_config.h"
|
|
#include "NWK_INTERFACE/Include/protocol.h"
|
|
#include "mac_api.h"
|
|
#include "mac_mcps.h"
|
|
#include "Common_Protocols/ipv6_constants.h"
|
|
#include "socket_api.h"
|
|
#include "6LoWPAN/MAC/mac_helper.h"
|
|
#include "6LoWPAN/MAC/mpx_api.h"
|
|
#include "6LoWPAN/ws/ws_config.h"
|
|
#include "6LoWPAN/ws/ws_eapol_pdu.h"
|
|
|
|
#ifdef HAVE_WS
|
|
|
|
#define TRACE_GROUP "wsep"
|
|
|
|
typedef struct {
|
|
uint8_t handle;
|
|
void *data_ptr;
|
|
void *buffer;
|
|
ns_list_link_t link;
|
|
} eapol_pdu_msdu_t;
|
|
|
|
typedef NS_LIST_HEAD(eapol_pdu_msdu_t, link) eapol_pdu_msdu_list_t;
|
|
|
|
typedef struct {
|
|
uint8_t priority;
|
|
ws_eapol_pdu_address_check *addr_check;
|
|
ws_eapol_pdu_receive *receive;
|
|
ns_list_link_t link;
|
|
} eapol_pdu_recv_cb_t;
|
|
|
|
typedef NS_LIST_HEAD(eapol_pdu_recv_cb_t, link) eapol_pdu_recv_cb_list_t;
|
|
|
|
typedef struct {
|
|
eapol_pdu_recv_cb_list_t recv_cb_list; /**< List of receive callbacks */
|
|
eapol_pdu_msdu_list_t msdu_list; /**< MSDU list */
|
|
ws_eapol_pdu_receive *receive; /**< data receive callback */
|
|
protocol_interface_info_entry_t *interface_ptr; /**< Interface pointer */
|
|
mpx_api_t *mpx_api; /**< MPX api */
|
|
uint16_t mpx_user_id; /**< MPX user identifier */
|
|
uint8_t msdu_handle; /**< MSDU handle */
|
|
ns_list_link_t link; /**< Link */
|
|
} eapol_pdu_data_t;
|
|
|
|
static void ws_eapol_pdu_mpx_data_confirm(const mpx_api_t *api, const struct mcps_data_conf_s *data);
|
|
static void ws_eapol_pdu_mpx_data_indication(const mpx_api_t *api, const struct mcps_data_ind_s *data);
|
|
static void ws_eapol_pdu_data_request_primitiv_set(mcps_data_req_t *dataReq, protocol_interface_info_entry_t *cur);
|
|
static eapol_pdu_data_t *ws_eapol_pdu_data_get(protocol_interface_info_entry_t *interface_ptr);
|
|
|
|
static NS_LIST_DEFINE(eapol_pdu_data_list, eapol_pdu_data_t, link);
|
|
|
|
int8_t ws_eapol_pdu_init(protocol_interface_info_entry_t *interface_ptr)
|
|
{
|
|
if (!interface_ptr) {
|
|
return -1;
|
|
}
|
|
|
|
if (ws_eapol_pdu_data_get(interface_ptr) != NULL) {
|
|
return 0;
|
|
}
|
|
|
|
eapol_pdu_data_t *eapol_pdu_data = ns_dyn_mem_alloc(sizeof(eapol_pdu_data_t));
|
|
if (!eapol_pdu_data) {
|
|
return -1;
|
|
}
|
|
|
|
eapol_pdu_data->interface_ptr = interface_ptr;
|
|
ns_list_init(&eapol_pdu_data->recv_cb_list);
|
|
ns_list_init(&eapol_pdu_data->msdu_list);
|
|
eapol_pdu_data->msdu_handle = 0;
|
|
|
|
ns_list_add_to_end(&eapol_pdu_data_list, eapol_pdu_data);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int8_t ws_eapol_pdu_delete(protocol_interface_info_entry_t *interface_ptr)
|
|
{
|
|
if (!interface_ptr) {
|
|
return -1;
|
|
}
|
|
|
|
eapol_pdu_data_t *eapol_pdu_data = ws_eapol_pdu_data_get(interface_ptr);
|
|
|
|
if (!eapol_pdu_data) {
|
|
return -1;
|
|
}
|
|
|
|
ns_list_foreach_safe(eapol_pdu_recv_cb_t, cb_entry, &eapol_pdu_data->recv_cb_list) {
|
|
ns_list_remove(&eapol_pdu_data->recv_cb_list, cb_entry);
|
|
ns_dyn_mem_free(cb_entry);
|
|
}
|
|
|
|
ns_list_foreach_safe(eapol_pdu_msdu_t, msdu_entry, &eapol_pdu_data->msdu_list) {
|
|
ns_list_remove(&eapol_pdu_data->msdu_list, msdu_entry);
|
|
ns_dyn_mem_free(msdu_entry);
|
|
}
|
|
|
|
ns_list_remove(&eapol_pdu_data_list, eapol_pdu_data);
|
|
ns_dyn_mem_free(eapol_pdu_data);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int8_t ws_eapol_pdu_cb_register(protocol_interface_info_entry_t *interface_ptr, const eapol_pdu_recv_cb_data_t *cb_data)
|
|
{
|
|
if (!interface_ptr || !cb_data) {
|
|
return -1;
|
|
}
|
|
|
|
eapol_pdu_data_t *eapol_pdu_data = ws_eapol_pdu_data_get(interface_ptr);
|
|
|
|
if (!eapol_pdu_data) {
|
|
return -1;
|
|
}
|
|
|
|
eapol_pdu_recv_cb_t *new_cb = ns_dyn_mem_alloc(sizeof(eapol_pdu_recv_cb_t));
|
|
if (!new_cb) {
|
|
return -1;
|
|
}
|
|
|
|
new_cb->priority = cb_data->priority;
|
|
new_cb->addr_check = cb_data->addr_check;
|
|
new_cb->receive = cb_data->receive;
|
|
|
|
ns_list_foreach(eapol_pdu_recv_cb_t, entry, &eapol_pdu_data->recv_cb_list) {
|
|
if (new_cb->priority <= entry->priority) {
|
|
ns_list_add_before(&eapol_pdu_data->recv_cb_list, entry, new_cb);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
ns_list_add_to_end(&eapol_pdu_data->recv_cb_list, new_cb);
|
|
return 0;
|
|
}
|
|
|
|
int8_t ws_eapol_pdu_cb_unregister(protocol_interface_info_entry_t *interface_ptr, const eapol_pdu_recv_cb_data_t *cb_data)
|
|
{
|
|
if (!interface_ptr || !cb_data) {
|
|
return -1;
|
|
}
|
|
|
|
eapol_pdu_data_t *eapol_pdu_data = ws_eapol_pdu_data_get(interface_ptr);
|
|
|
|
if (!eapol_pdu_data) {
|
|
return -1;
|
|
}
|
|
|
|
ns_list_foreach_safe(eapol_pdu_recv_cb_t, entry, &eapol_pdu_data->recv_cb_list) {
|
|
if (entry->receive == cb_data->receive) {
|
|
ns_list_remove(&eapol_pdu_data->recv_cb_list, entry);
|
|
ns_dyn_mem_free(entry);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
int8_t ws_eapol_pdu_send_to_mpx(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64, void *data, uint16_t size, void *buffer)
|
|
{
|
|
eapol_pdu_data_t *eapol_pdu_data = ws_eapol_pdu_data_get(interface_ptr);
|
|
|
|
if (!eapol_pdu_data) {
|
|
return -1;
|
|
}
|
|
|
|
mcps_data_req_t data_request;
|
|
ws_eapol_pdu_data_request_primitiv_set(&data_request, eapol_pdu_data->interface_ptr);
|
|
|
|
eapol_pdu_msdu_t *msdu_entry = ns_dyn_mem_temporary_alloc(sizeof(eapol_pdu_msdu_t));
|
|
if (!msdu_entry) {
|
|
return -1;
|
|
}
|
|
msdu_entry->data_ptr = data;
|
|
msdu_entry->buffer = buffer;
|
|
msdu_entry->handle = eapol_pdu_data->msdu_handle++;
|
|
ns_list_add_to_start(&eapol_pdu_data->msdu_list, msdu_entry);
|
|
|
|
memcpy(data_request.DstAddr, eui_64, 8);
|
|
data_request.msdu = data;
|
|
data_request.msduLength = size;
|
|
|
|
eapol_pdu_data->mpx_api->mpx_data_request(eapol_pdu_data->mpx_api, &data_request, eapol_pdu_data->mpx_user_id);
|
|
return 0;
|
|
}
|
|
|
|
static void ws_eapol_pdu_data_request_primitiv_set(mcps_data_req_t *dataReq, protocol_interface_info_entry_t *cur)
|
|
{
|
|
memset(dataReq, 0, sizeof(mcps_data_req_t));
|
|
|
|
dataReq->InDirectTx = false;
|
|
dataReq->TxAckReq = true;
|
|
dataReq->SrcAddrMode = ADDR_802_15_4_LONG;
|
|
dataReq->DstAddrMode = ADDR_802_15_4_LONG;
|
|
dataReq->DstPANId = mac_helper_panid_get(cur);
|
|
}
|
|
|
|
int8_t ws_eapol_pdu_mpx_register(protocol_interface_info_entry_t *interface_ptr, struct mpx_api_s *mpx_api, uint16_t mpx_user_id)
|
|
{
|
|
if (!interface_ptr) {
|
|
return -1;
|
|
}
|
|
|
|
eapol_pdu_data_t *eapol_pdu_data = ws_eapol_pdu_data_get(interface_ptr);
|
|
|
|
if (!eapol_pdu_data) {
|
|
return -1;
|
|
}
|
|
|
|
if (!mpx_api && eapol_pdu_data->mpx_api) {
|
|
//Disable Data Callbacks from MPX Class
|
|
eapol_pdu_data->mpx_api->mpx_user_registration(eapol_pdu_data->mpx_api, NULL, NULL, eapol_pdu_data->mpx_user_id);
|
|
}
|
|
|
|
eapol_pdu_data->mpx_api = mpx_api;
|
|
eapol_pdu_data->mpx_user_id = mpx_user_id;
|
|
|
|
if (eapol_pdu_data->mpx_api) {
|
|
eapol_pdu_data->mpx_api->mpx_user_registration(eapol_pdu_data->mpx_api, ws_eapol_pdu_mpx_data_confirm, ws_eapol_pdu_mpx_data_indication, eapol_pdu_data->mpx_user_id);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void ws_eapol_pdu_mpx_data_confirm(const mpx_api_t *api, const struct mcps_data_conf_s *data)
|
|
{
|
|
eapol_pdu_data_t *eapol_pdu_data = NULL;
|
|
|
|
ns_list_foreach(eapol_pdu_data_t, entry, &eapol_pdu_data_list) {
|
|
if (entry->mpx_api == api) {
|
|
eapol_pdu_data = entry;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!eapol_pdu_data) {
|
|
return;
|
|
}
|
|
|
|
ns_list_foreach(eapol_pdu_msdu_t, msdu, &eapol_pdu_data->msdu_list) {
|
|
if (msdu->handle == data->msduHandle) {
|
|
ns_dyn_mem_free(msdu->buffer);
|
|
ns_list_remove(&eapol_pdu_data->msdu_list, msdu);
|
|
ns_dyn_mem_free(msdu);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void ws_eapol_pdu_mpx_data_indication(const mpx_api_t *api, const struct mcps_data_ind_s *data)
|
|
{
|
|
if (!data || !data->msduLength || !data->msdu_ptr) {
|
|
return;
|
|
}
|
|
|
|
eapol_pdu_data_t *eapol_pdu_data = NULL;
|
|
|
|
ns_list_foreach(eapol_pdu_data_t, entry, &eapol_pdu_data_list) {
|
|
if (entry->mpx_api == api) {
|
|
eapol_pdu_data = entry;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!eapol_pdu_data) {
|
|
return;
|
|
}
|
|
|
|
ns_list_foreach(eapol_pdu_recv_cb_t, entry, &eapol_pdu_data->recv_cb_list) {
|
|
if (entry->addr_check(eapol_pdu_data->interface_ptr, data->SrcAddr) >= 0) {
|
|
entry->receive(eapol_pdu_data->interface_ptr, data->SrcAddr, data->msdu_ptr, data->msduLength);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static eapol_pdu_data_t *ws_eapol_pdu_data_get(protocol_interface_info_entry_t *interface_ptr)
|
|
{
|
|
eapol_pdu_data_t *eapol_pdu_data = NULL;
|
|
|
|
ns_list_foreach(eapol_pdu_data_t, entry, &eapol_pdu_data_list) {
|
|
if (entry->interface_ptr == interface_ptr) {
|
|
eapol_pdu_data = entry;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return eapol_pdu_data;
|
|
}
|
|
|
|
#endif /* HAVE_WS */
|
|
|