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_auth_relay.c Source File

ws_eapol_auth_relay.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 #include "6LoWPAN/ws/ws_eapol_relay_lib.h"
00035 #include "6LoWPAN/ws/ws_eapol_auth_relay.h"
00036 #include "common_functions.h"
00037 
00038 #ifdef HAVE_WS
00039 #ifdef HAVE_PAE_AUTH
00040 
00041 #define TRACE_GROUP "wsar"
00042 
00043 typedef struct {
00044     protocol_interface_info_entry_t *interface_ptr;         /**< Interface pointer */
00045     ns_address_t remote_addr;                               /**< Remote address and port */
00046     ns_address_t relay_addr;                                /**< Relay address */
00047     int8_t socket_id;                                       /**< Socket ID for relay */
00048     ns_list_link_t link;                                    /**< Link */
00049 } eapol_auth_relay_t;
00050 
00051 static eapol_auth_relay_t *ws_eapol_auth_relay_get(protocol_interface_info_entry_t *interface_ptr);
00052 static void ws_eapol_auth_relay_socket_cb(void *cb);
00053 static int8_t ws_eapol_auth_relay_send_to_kmp(eapol_auth_relay_t *eapol_auth_relay, const uint8_t *eui_64, const uint8_t *ip_addr, uint16_t port, const void *data, uint16_t data_len);
00054 
00055 static NS_LIST_DEFINE(eapol_auth_relay_list, eapol_auth_relay_t, link);
00056 
00057 int8_t ws_eapol_auth_relay_start(protocol_interface_info_entry_t *interface_ptr, uint16_t local_port, const uint8_t *remote_addr, uint16_t remote_port)
00058 {
00059     if (!interface_ptr || !remote_addr) {
00060         return -1;
00061     }
00062 
00063     if (ws_eapol_auth_relay_get(interface_ptr)) {
00064         return 0;
00065     }
00066 
00067     eapol_auth_relay_t *eapol_auth_relay = ns_dyn_mem_alloc(sizeof(eapol_auth_relay_t));
00068     if (!eapol_auth_relay) {
00069         return -1;
00070     }
00071 
00072     eapol_auth_relay->interface_ptr = interface_ptr;
00073 
00074     eapol_auth_relay->remote_addr.type = ADDRESS_IPV6;
00075     memcpy(&eapol_auth_relay->relay_addr.address, remote_addr, 16);
00076     eapol_auth_relay->relay_addr.identifier = remote_port;
00077 
00078     eapol_auth_relay->socket_id = socket_open(IPV6_NH_UDP, local_port, &ws_eapol_auth_relay_socket_cb);
00079     if (eapol_auth_relay->socket_id < 0) {
00080         ns_dyn_mem_free(eapol_auth_relay);
00081         return -1;
00082     }
00083 
00084     ns_list_add_to_end(&eapol_auth_relay_list, eapol_auth_relay);
00085 
00086     return 0;
00087 }
00088 
00089 int8_t ws_eapol_auth_relay_delete(protocol_interface_info_entry_t *interface_ptr)
00090 {
00091     if (!interface_ptr) {
00092         return -1;
00093     }
00094 
00095     eapol_auth_relay_t *eapol_auth_relay = ws_eapol_auth_relay_get(interface_ptr);
00096     if (!eapol_auth_relay) {
00097         return -1;
00098     }
00099 
00100     socket_close(eapol_auth_relay->socket_id);
00101 
00102     ns_list_remove(&eapol_auth_relay_list, eapol_auth_relay);
00103     ns_dyn_mem_free(eapol_auth_relay);
00104 
00105     return 0;
00106 }
00107 
00108 static eapol_auth_relay_t *ws_eapol_auth_relay_get(protocol_interface_info_entry_t *interface_ptr)
00109 {
00110     ns_list_foreach(eapol_auth_relay_t, entry, &eapol_auth_relay_list) {
00111         if (entry->interface_ptr == interface_ptr) {
00112             return entry;
00113         }
00114     }
00115 
00116     return NULL;
00117 }
00118 
00119 static void ws_eapol_auth_relay_socket_cb(void *cb)
00120 {
00121     socket_callback_t *cb_data = cb;
00122 
00123     if (cb_data->event_type != SOCKET_DATA) {
00124         return;
00125     }
00126 
00127     eapol_auth_relay_t *eapol_auth_relay = NULL;
00128 
00129     ns_list_foreach(eapol_auth_relay_t, entry, &eapol_auth_relay_list) {
00130         if (entry->socket_id == cb_data->socket_id) {
00131             eapol_auth_relay = entry;
00132             break;
00133         }
00134     }
00135 
00136     if (!eapol_auth_relay) {
00137         return;
00138     }
00139 
00140     uint8_t *socket_pdu = ns_dyn_mem_temporary_alloc(cb_data->d_len);
00141     if (!socket_pdu) {
00142         return;
00143     }
00144 
00145     ns_address_t src_addr;
00146 
00147     if (socket_recvfrom(cb_data->socket_id, socket_pdu, cb_data->d_len, 0, &src_addr) != cb_data->d_len) {
00148         ns_dyn_mem_free(socket_pdu);
00149         return;
00150     }
00151 
00152     // Message from source port 10254 (KMP service) -> to IP relay on node or on authenticator
00153     if (src_addr.identifier == eapol_auth_relay->relay_addr.identifier) {
00154         uint8_t *ptr = socket_pdu;
00155         uint8_t *eui_64;
00156         ns_address_t relay_ip_addr;
00157         relay_ip_addr.type = ADDRESS_IPV6;
00158         memcpy(relay_ip_addr.address, ptr, 16);
00159         ptr += 16;
00160         relay_ip_addr.identifier = common_read_16_bit(ptr);
00161         ptr += 2;
00162         eui_64 = ptr;
00163         ptr += 8;
00164         uint16_t data_len = cb_data->d_len - 26;
00165         ws_eapol_relay_lib_send_to_relay(eapol_auth_relay->socket_id, eui_64, &relay_ip_addr,
00166                                          ptr, data_len);
00167         ns_dyn_mem_free(socket_pdu);
00168         // Other source port (either 10253 or node relay source port) -> to KMP service
00169     } else {
00170         uint8_t *ptr = socket_pdu;
00171         ws_eapol_auth_relay_send_to_kmp(eapol_auth_relay, ptr, src_addr.address, src_addr.identifier,
00172                                         ptr + 8, cb_data->d_len - 8);
00173         ns_dyn_mem_free(socket_pdu);
00174     }
00175 }
00176 
00177 static int8_t ws_eapol_auth_relay_send_to_kmp(eapol_auth_relay_t *eapol_auth_relay, const uint8_t *eui_64, const uint8_t *ip_addr, uint16_t port, const void *data, uint16_t data_len)
00178 {
00179     ns_address_t dest_addr = eapol_auth_relay->relay_addr;
00180 
00181     uint8_t temp_array[26];
00182     ns_iovec_t msg_iov[2];
00183     ns_msghdr_t msghdr;
00184     //Set messages name buffer
00185     msghdr.msg_name = &dest_addr;
00186     msghdr.msg_namelen = sizeof(dest_addr);
00187     msghdr.msg_iov = &msg_iov[0];
00188     msghdr.msg_iovlen = 2;
00189     msghdr.msg_control = NULL;
00190     msghdr.msg_controllen = 0;
00191     uint8_t *ptr = temp_array;
00192     memcpy(ptr, ip_addr, 16);
00193     ptr += 16;
00194     ptr = common_write_16_bit(port, ptr);
00195     memcpy(ptr, eui_64, 8);
00196     msg_iov[0].iov_base = temp_array;
00197     msg_iov[0].iov_len = 26;
00198     msg_iov[1].iov_base = (void *)data;
00199     msg_iov[1].iov_len = data_len;
00200     socket_sendmsg(eapol_auth_relay->socket_id, &msghdr, NS_MSG_LEGACY0);
00201     return 0;
00202 }
00203 
00204 #endif /* HAVE_PAE_AUTH */
00205 #endif /* HAVE_WS */