Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ws_eapol_pdu.c Source File

ws_eapol_pdu.c

00001 /*
00002  * Copyright (c) 2018-2019, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 #include "nsconfig.h"
00019 #include <string.h>
00020 #include "ns_types.h"
00021 #include "ns_list.h"
00022 #include "ns_trace.h"
00023 #include "nsdynmemLIB.h"
00024 #include "fhss_config.h "
00025 #include "NWK_INTERFACE/Include/protocol.h"
00026 #include "mac_api.h"
00027 #include "mac_mcps.h"
00028 #include "Common_Protocols/ipv6_constants.h"
00029 #include "socket_api.h"
00030 #include "6LoWPAN/MAC/mac_helper.h"
00031 #include "6LoWPAN/MAC/mpx_api.h"
00032 #include "6LoWPAN/ws/ws_config.h"
00033 #include "6LoWPAN/ws/ws_eapol_pdu.h"
00034 
00035 #ifdef HAVE_WS
00036 
00037 #define TRACE_GROUP "wsep"
00038 
00039 typedef struct {
00040     void *data_ptr;
00041     void *buffer;
00042     ws_eapol_pdu_tx_status *tx_status;
00043     uint8_t tx_identifier;
00044     uint8_t handle;
00045     ns_list_link_t link;
00046 } eapol_pdu_msdu_t;
00047 
00048 typedef NS_LIST_HEAD (eapol_pdu_msdu_t, link) eapol_pdu_msdu_list_t;
00049 
00050 typedef struct {
00051     uint8_t priority;
00052     ws_eapol_pdu_address_check *addr_check;
00053     ws_eapol_pdu_receive *receive;
00054     ns_list_link_t link;
00055 } eapol_pdu_recv_cb_t;
00056 
00057 typedef NS_LIST_HEAD (eapol_pdu_recv_cb_t, link) eapol_pdu_recv_cb_list_t;
00058 
00059 typedef struct {
00060     eapol_pdu_recv_cb_list_t recv_cb_list;                 /**< List of receive callbacks */
00061     eapol_pdu_msdu_list_t msdu_list;                       /**< MSDU list */
00062     ws_eapol_pdu_receive *receive;                         /**< data receive callback */
00063     protocol_interface_info_entry_t *interface_ptr;        /**< Interface pointer */
00064     mpx_api_t *mpx_api;                                    /**< MPX api */
00065     uint16_t mpx_user_id;                                  /**< MPX user identifier */
00066     uint8_t msdu_handle;                                   /**< MSDU handle */
00067     ns_list_link_t link;                                   /**< Link */
00068 } eapol_pdu_data_t;
00069 
00070 static void ws_eapol_pdu_mpx_data_confirm(const mpx_api_t *api, const struct mcps_data_conf_s *data);
00071 static void ws_eapol_pdu_mpx_data_indication(const mpx_api_t *api, const struct mcps_data_ind_s *data);
00072 static void ws_eapol_pdu_data_request_primitiv_set(mcps_data_req_t *dataReq, protocol_interface_info_entry_t *cur);
00073 static eapol_pdu_data_t *ws_eapol_pdu_data_get(protocol_interface_info_entry_t *interface_ptr);
00074 
00075 static NS_LIST_DEFINE(eapol_pdu_data_list, eapol_pdu_data_t, link);
00076 
00077 int8_t ws_eapol_pdu_init(protocol_interface_info_entry_t *interface_ptr)
00078 {
00079     if (!interface_ptr) {
00080         return -1;
00081     }
00082 
00083     if (ws_eapol_pdu_data_get(interface_ptr) != NULL) {
00084         return 0;
00085     }
00086 
00087     eapol_pdu_data_t *eapol_pdu_data = ns_dyn_mem_alloc(sizeof(eapol_pdu_data_t));
00088     if (!eapol_pdu_data) {
00089         return -1;
00090     }
00091 
00092     eapol_pdu_data->interface_ptr = interface_ptr;
00093     ns_list_init(&eapol_pdu_data->recv_cb_list);
00094     ns_list_init(&eapol_pdu_data->msdu_list);
00095     eapol_pdu_data->msdu_handle = 0;
00096 
00097     ns_list_add_to_end(&eapol_pdu_data_list, eapol_pdu_data);
00098 
00099     return 0;
00100 }
00101 
00102 int8_t ws_eapol_pdu_delete(protocol_interface_info_entry_t *interface_ptr)
00103 {
00104     if (!interface_ptr) {
00105         return -1;
00106     }
00107 
00108     eapol_pdu_data_t *eapol_pdu_data = ws_eapol_pdu_data_get(interface_ptr);
00109 
00110     if (!eapol_pdu_data) {
00111         return -1;
00112     }
00113 
00114     ns_list_foreach_safe(eapol_pdu_recv_cb_t, cb_entry, &eapol_pdu_data->recv_cb_list) {
00115         ns_list_remove(&eapol_pdu_data->recv_cb_list, cb_entry);
00116         ns_dyn_mem_free(cb_entry);
00117     }
00118 
00119     ns_list_foreach_safe(eapol_pdu_msdu_t, msdu_entry, &eapol_pdu_data->msdu_list) {
00120         ns_list_remove(&eapol_pdu_data->msdu_list, msdu_entry);
00121         ns_dyn_mem_free(msdu_entry);
00122     }
00123 
00124     ns_list_remove(&eapol_pdu_data_list, eapol_pdu_data);
00125     ns_dyn_mem_free(eapol_pdu_data);
00126 
00127     return 0;
00128 }
00129 
00130 int8_t ws_eapol_pdu_cb_register(protocol_interface_info_entry_t *interface_ptr, const eapol_pdu_recv_cb_data_t *cb_data)
00131 {
00132     if (!interface_ptr || !cb_data) {
00133         return -1;
00134     }
00135 
00136     eapol_pdu_data_t *eapol_pdu_data =  ws_eapol_pdu_data_get(interface_ptr);
00137 
00138     if (!eapol_pdu_data) {
00139         return -1;
00140     }
00141 
00142     eapol_pdu_recv_cb_t *new_cb = ns_dyn_mem_alloc(sizeof(eapol_pdu_recv_cb_t));
00143     if (!new_cb) {
00144         return -1;
00145     }
00146 
00147     new_cb->priority = cb_data->priority;
00148     new_cb->addr_check = cb_data->addr_check;
00149     new_cb->receive = cb_data->receive;
00150 
00151     ns_list_foreach(eapol_pdu_recv_cb_t, entry, &eapol_pdu_data->recv_cb_list) {
00152         if (new_cb->priority <= entry->priority) {
00153             ns_list_add_before(&eapol_pdu_data->recv_cb_list, entry, new_cb);
00154             return 0;
00155         }
00156     }
00157 
00158     ns_list_add_to_end(&eapol_pdu_data->recv_cb_list, new_cb);
00159     return 0;
00160 }
00161 
00162 int8_t ws_eapol_pdu_cb_unregister(protocol_interface_info_entry_t *interface_ptr, const eapol_pdu_recv_cb_data_t *cb_data)
00163 {
00164     if (!interface_ptr || !cb_data) {
00165         return -1;
00166     }
00167 
00168     eapol_pdu_data_t *eapol_pdu_data = ws_eapol_pdu_data_get(interface_ptr);
00169 
00170     if (!eapol_pdu_data) {
00171         return -1;
00172     }
00173 
00174     ns_list_foreach_safe(eapol_pdu_recv_cb_t, entry, &eapol_pdu_data->recv_cb_list) {
00175         if (entry->receive == cb_data->receive) {
00176             ns_list_remove(&eapol_pdu_data->recv_cb_list, entry);
00177             ns_dyn_mem_free(entry);
00178             return 0;
00179         }
00180     }
00181 
00182     return -1;
00183 }
00184 
00185 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, ws_eapol_pdu_tx_status *tx_status, uint8_t tx_identifier)
00186 {
00187     eapol_pdu_data_t *eapol_pdu_data = ws_eapol_pdu_data_get(interface_ptr);
00188 
00189     if (!eapol_pdu_data) {
00190         return -1;
00191     }
00192 
00193     mcps_data_req_t data_request;
00194     ws_eapol_pdu_data_request_primitiv_set(&data_request, eapol_pdu_data->interface_ptr);
00195 
00196     eapol_pdu_msdu_t *msdu_entry = ns_dyn_mem_temporary_alloc(sizeof(eapol_pdu_msdu_t));
00197     if (!msdu_entry) {
00198         return -1;
00199     }
00200     msdu_entry->data_ptr = data;
00201     msdu_entry->buffer = buffer;
00202     msdu_entry->handle = eapol_pdu_data->msdu_handle;
00203     msdu_entry->tx_status = tx_status;
00204     msdu_entry->tx_identifier = tx_identifier;
00205     ns_list_add_to_start(&eapol_pdu_data->msdu_list, msdu_entry);
00206 
00207     memcpy(data_request.DstAddr, eui_64, 8);
00208     data_request.msdu = data;
00209     data_request.msduLength = size;
00210     data_request.msduHandle = eapol_pdu_data->msdu_handle;
00211 
00212     eapol_pdu_data->msdu_handle++;
00213 
00214     eapol_pdu_data->mpx_api->mpx_data_request(eapol_pdu_data->mpx_api, &data_request, eapol_pdu_data->mpx_user_id);
00215     return 0;
00216 }
00217 
00218 static void ws_eapol_pdu_data_request_primitiv_set(mcps_data_req_t *dataReq, protocol_interface_info_entry_t *cur)
00219 {
00220     memset(dataReq, 0, sizeof(mcps_data_req_t));
00221 
00222     dataReq->InDirectTx = false;
00223     dataReq->TxAckReq = true;
00224     dataReq->SrcAddrMode = ADDR_802_15_4_LONG ;
00225     dataReq->DstAddrMode = ADDR_802_15_4_LONG ;
00226     dataReq->DstPANId = mac_helper_panid_get(cur);
00227 }
00228 
00229 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)
00230 {
00231     if (!interface_ptr) {
00232         return -1;
00233     }
00234 
00235     eapol_pdu_data_t *eapol_pdu_data = ws_eapol_pdu_data_get(interface_ptr);
00236 
00237     if (!eapol_pdu_data) {
00238         return -1;
00239     }
00240 
00241     if (!mpx_api && eapol_pdu_data->mpx_api) {
00242         //Disable Data Callbacks from MPX Class
00243         eapol_pdu_data->mpx_api->mpx_user_registration(eapol_pdu_data->mpx_api, NULL, NULL, eapol_pdu_data->mpx_user_id);
00244     }
00245 
00246     eapol_pdu_data->mpx_api = mpx_api;
00247     eapol_pdu_data->mpx_user_id = mpx_user_id;
00248 
00249     if (eapol_pdu_data->mpx_api) {
00250         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);
00251     }
00252     return 0;
00253 }
00254 
00255 static void ws_eapol_pdu_mpx_data_confirm(const mpx_api_t *api, const struct mcps_data_conf_s *data)
00256 {
00257     eapol_pdu_data_t *eapol_pdu_data = NULL;
00258 
00259     ns_list_foreach(eapol_pdu_data_t, entry, &eapol_pdu_data_list) {
00260         if (entry->mpx_api == api) {
00261             eapol_pdu_data = entry;
00262             break;
00263         }
00264     }
00265 
00266     if (!eapol_pdu_data) {
00267         return;
00268     }
00269 
00270     ns_list_foreach(eapol_pdu_msdu_t, msdu, &eapol_pdu_data->msdu_list) {
00271         if (msdu->handle == data->msduHandle) {
00272             if (msdu->tx_status) {
00273                 eapol_pdu_tx_status_e status = EAPOL_PDU_TX_ERR_UNSPEC;
00274                 if (data->status == MLME_SUCCESS) {
00275                     status = EAPOL_PDU_TX_OK;
00276                 } else if (data->status == MLME_TX_NO_ACK) {
00277                     status = EAPOL_PDU_TX_ERR_TX_NO_ACK;
00278                 }
00279                 msdu->tx_status(eapol_pdu_data->interface_ptr, status, msdu->tx_identifier);
00280             }
00281             ns_dyn_mem_free(msdu->buffer);
00282             ns_list_remove(&eapol_pdu_data->msdu_list, msdu);
00283             ns_dyn_mem_free(msdu);
00284             return;
00285         }
00286     }
00287 }
00288 
00289 static void ws_eapol_pdu_mpx_data_indication(const mpx_api_t *api, const struct mcps_data_ind_s *data)
00290 {
00291     if (!data || !data->msduLength || !data->msdu_ptr) {
00292         return;
00293     }
00294 
00295     eapol_pdu_data_t *eapol_pdu_data = NULL;
00296 
00297     ns_list_foreach(eapol_pdu_data_t, entry, &eapol_pdu_data_list) {
00298         if (entry->mpx_api == api) {
00299             eapol_pdu_data = entry;
00300             break;
00301         }
00302     }
00303 
00304     if (!eapol_pdu_data) {
00305         return;
00306     }
00307 
00308     ns_list_foreach(eapol_pdu_recv_cb_t, entry, &eapol_pdu_data->recv_cb_list) {
00309         if (entry->addr_check(eapol_pdu_data->interface_ptr, data->SrcAddr) >= 0) {
00310             entry->receive(eapol_pdu_data->interface_ptr, data->SrcAddr, data->msdu_ptr, data->msduLength);
00311             break;
00312         }
00313     }
00314 }
00315 
00316 static eapol_pdu_data_t *ws_eapol_pdu_data_get(protocol_interface_info_entry_t *interface_ptr)
00317 {
00318     eapol_pdu_data_t *eapol_pdu_data = NULL;
00319 
00320     ns_list_foreach(eapol_pdu_data_t, entry, &eapol_pdu_data_list) {
00321         if (entry->interface_ptr == interface_ptr) {
00322             eapol_pdu_data = entry;
00323             break;
00324         }
00325     }
00326 
00327     return eapol_pdu_data;
00328 }
00329 
00330 #endif /* HAVE_WS */
00331