BA
/
BaBoRo1
Embed:
(wiki syntax)
Show/hide line numbers
nd_proxy.c
00001 /* 00002 * Copyright (c) 2015-2017, 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 #ifdef HAVE_ND_PROXY 00020 #include "ns_types.h" 00021 #include "common_functions.h" 00022 #include "ns_trace.h" 00023 #include "string.h" 00024 #include "nsdynmemLIB.h" 00025 #include "ns_list.h" 00026 #include "Service_Libs/nd_proxy/nd_proxy.h" 00027 00028 #define TRACE_GROUP "prox" 00029 00030 /** 00031 * Downstream Interface list 00032 */ 00033 typedef struct nd_proxy_downstream_list { 00034 int8_t id; /**< Proxy Interface Id*/ 00035 bridge_state_update_cb *bridge_status_update; /**< Update bridge state */ 00036 nd_proxy_req_cb *nd_proxy_validation; /**< Validate NS ND proxy response */ 00037 ns_list_link_t link; 00038 } nd_proxy_downstream_list_s; 00039 00040 /** 00041 * Upstream Interface list 00042 */ 00043 typedef struct nd_proxy_upstream_list { 00044 int8_t id; /**< Upstream Interface Id*/ 00045 nd_proxy_req_cb *route_on_link_validation; /**< Mesh Can validate OnLink Route */ 00046 ns_list_link_t link; 00047 } nd_proxy_upstream_list_s; 00048 00049 /** 00050 * Linked Downstream interface list to Upstream 00051 */ 00052 typedef struct nd_proxy_downstream_interfaces_list { 00053 int8_t id; /**< Downstream Interface Id*/ 00054 ns_list_link_t link; 00055 } nd_proxy_downstream_interfaces_list_s; 00056 00057 typedef NS_LIST_HEAD (nd_proxy_upstream_list_s, link) upstream_interface_list_t; 00058 00059 typedef NS_LIST_HEAD (nd_proxy_downstream_list_s, link) downstream_interface_list_t; 00060 00061 typedef NS_LIST_HEAD (nd_proxy_downstream_interfaces_list_s, link) proxy_connected_downstream_list_t; 00062 00063 /** 00064 * Linked Upstream and Downstream interface list 00065 */ 00066 typedef struct nd_proxy_connected_list { 00067 int8_t id; /**< Upstream Interface Id*/ 00068 proxy_connected_downstream_list_t connected_downstream_list; /**< Linked Downstream Interfaces to this interface*/ 00069 ns_list_link_t link; 00070 } nd_proxy_connected_list_s; 00071 00072 typedef NS_LIST_HEAD (nd_proxy_connected_list_s, link) proxy_connected_interface_list_t; 00073 00074 /* List of registered Upstream interfaces */ 00075 static upstream_interface_list_t upstream_interface_list; 00076 00077 /* List of registered Downstream interfaces */ 00078 static downstream_interface_list_t downstream_interface_list; 00079 00080 /* List of connected Upstream interfaces */ 00081 static proxy_connected_interface_list_t paired_interface_list; 00082 00083 /** 00084 * Get or allocate new Downstream interface entry 00085 * 00086 */ 00087 static nd_proxy_downstream_list_s * proxy_cache_downstream_interface_allocate(int8_t interface , downstream_interface_list_t *list) 00088 { 00089 ns_list_foreach(nd_proxy_downstream_list_s, e, list) { 00090 if (e->id == interface) { 00091 return e; 00092 } 00093 } 00094 nd_proxy_downstream_list_s *entry = ns_dyn_mem_alloc(sizeof(nd_proxy_downstream_list_s)); 00095 if (entry) { 00096 entry->id = interface; 00097 ns_list_add_to_start(list, entry); 00098 } 00099 00100 return entry; 00101 } 00102 00103 /** 00104 * Get or allocate new Upstream interface entry 00105 * 00106 */ 00107 static nd_proxy_upstream_list_s * proxy_cache_upstream_interface_allocate(int8_t interface , upstream_interface_list_t *list) 00108 { 00109 ns_list_foreach(nd_proxy_upstream_list_s, e, list) { 00110 if (e->id == interface) { 00111 return e; 00112 } 00113 } 00114 nd_proxy_upstream_list_s *entry = ns_dyn_mem_alloc(sizeof(nd_proxy_upstream_list_s)); 00115 if (entry) { 00116 entry->id = interface; 00117 ns_list_add_to_start(list, entry); 00118 } 00119 00120 return entry; 00121 } 00122 00123 /** 00124 * Get registered Downstream interface entry 00125 * 00126 */ 00127 static nd_proxy_downstream_list_s * proxy_cache_downstream_interface_get(int8_t interface , downstream_interface_list_t *list) 00128 { 00129 ns_list_foreach(nd_proxy_downstream_list_s, e, list) { 00130 if (e->id == interface) { 00131 return e; 00132 } 00133 } 00134 return NULL; 00135 } 00136 00137 /** 00138 * Get registered Upstream interface entry 00139 * 00140 */ 00141 static nd_proxy_upstream_list_s * proxy_cache_upstream_interface_get(int8_t interface , upstream_interface_list_t *list) 00142 { 00143 ns_list_foreach(nd_proxy_upstream_list_s, e, list) { 00144 if (e->id == interface) { 00145 return e; 00146 } 00147 } 00148 return NULL; 00149 } 00150 00151 /** 00152 * Get linked proxy entry by Upstream interface id 00153 * 00154 */ 00155 static nd_proxy_connected_list_s * proxy_upstream_conection_get(int8_t interface_id) 00156 { 00157 ns_list_foreach(nd_proxy_connected_list_s, e, &paired_interface_list) { 00158 if (e->id == interface_id) { 00159 return e; 00160 } 00161 } 00162 return NULL; 00163 } 00164 00165 /** 00166 * Get or allocate new proxy entry by Upstream interface id 00167 * 00168 */ 00169 static nd_proxy_connected_list_s * proxy_upstream_connection_allocate(int8_t interface_id) 00170 { 00171 ns_list_foreach(nd_proxy_connected_list_s, e, &paired_interface_list) { 00172 if (e->id == interface_id) { 00173 return e; 00174 } 00175 } 00176 00177 nd_proxy_connected_list_s *entry = ns_dyn_mem_alloc(sizeof(nd_proxy_connected_list_s)); 00178 if (entry) { 00179 entry->id = interface_id; 00180 ns_list_init(&entry->connected_downstream_list); 00181 ns_list_add_to_start(&paired_interface_list, entry); 00182 } 00183 return entry; 00184 } 00185 00186 /** 00187 * Link Downstream interface to allocated proxy 00188 * 00189 */ 00190 static bool proxy_downstream_conection_allocate(int8_t interface_id, proxy_connected_downstream_list_t *list) 00191 { 00192 ns_list_foreach(nd_proxy_downstream_interfaces_list_s, e, list) { 00193 if (e->id == interface_id) { 00194 return true; 00195 } 00196 } 00197 00198 nd_proxy_downstream_interfaces_list_s *entry = ns_dyn_mem_alloc(sizeof(nd_proxy_downstream_interfaces_list_s)); 00199 if (entry) { 00200 entry->id = interface_id; 00201 ns_list_add_to_start(list, entry); 00202 return true; 00203 } 00204 return false; 00205 } 00206 00207 /** 00208 * Remove Downstream interface from linked Upstream list 00209 * 00210 */ 00211 static bool proxy_cache_untie_connection_by_downstream(int8_t downstream_id) 00212 { 00213 bool ret_val = false; 00214 ns_list_foreach_safe(nd_proxy_connected_list_s, e, &paired_interface_list) { 00215 00216 ns_list_foreach_safe(nd_proxy_downstream_interfaces_list_s, downstream, &e->connected_downstream_list) { 00217 if (downstream->id == downstream_id) { 00218 //Remove from the list and free 00219 ns_list_remove(&e->connected_downstream_list, downstream); 00220 ns_dyn_mem_free(downstream); 00221 ret_val = true; 00222 } 00223 } 00224 00225 /* Free proxy connection if all mesh interfaces are disconnected */ 00226 if (ns_list_is_empty(&e->connected_downstream_list)) { 00227 //Remove connection from list and free memory 00228 ns_list_remove(&paired_interface_list, e); 00229 ns_dyn_mem_free(e); 00230 } 00231 00232 } 00233 return ret_val; 00234 } 00235 00236 /** 00237 * Remove Upstream interface from connected list 00238 * 00239 * Function will tell to mesh interface by registered function pointer disabled proxy functionality 00240 * 00241 */ 00242 static bool proxy_cache_untie_connection_by_upstream(int8_t upstream_id) 00243 { 00244 nd_proxy_downstream_list_s *downstream_interface; 00245 00246 ns_list_foreach_safe(nd_proxy_connected_list_s, e, &paired_interface_list) { 00247 00248 if (e->id != upstream_id) { 00249 continue; 00250 } 00251 00252 ns_list_foreach_safe(nd_proxy_downstream_interfaces_list_s, downstream, &e->connected_downstream_list) { 00253 //Remove from the list and free 00254 downstream_interface = proxy_cache_downstream_interface_get(downstream->id, &downstream_interface_list); 00255 if (downstream_interface) { 00256 //Indicate Downstream for missing Upstream 00257 if (downstream_interface->bridge_status_update) { 00258 downstream_interface->bridge_status_update(upstream_id, downstream->id, false); 00259 } 00260 } 00261 00262 ns_list_remove(&e->connected_downstream_list, downstream); 00263 ns_dyn_mem_free(downstream); 00264 } 00265 00266 //Remove connection from list and free memory 00267 ns_list_remove(&paired_interface_list, e); 00268 ns_dyn_mem_free(e); 00269 return true; 00270 00271 } 00272 return false; 00273 } 00274 00275 /** 00276 * Generate Proxy between Upstream and Downstream interface 00277 * 00278 * Function will tell to Downstream interface by registered function pointer enabled proxy functionality 00279 * 00280 */ 00281 static int proxy_cache_interface_enable_proxy(int8_t upstream_id, int8_t downstream_id) 00282 { 00283 //validate first current connection 00284 nd_proxy_connected_list_s *proxy = NULL; 00285 nd_proxy_downstream_list_s *downstream_interface = proxy_cache_downstream_interface_get(downstream_id, &downstream_interface_list); 00286 if (!downstream_interface) { 00287 tr_error("Unknown Downstream id"); 00288 return -1; 00289 } 00290 00291 if (!proxy_cache_upstream_interface_get(upstream_id , &upstream_interface_list)) { 00292 tr_error("Unknown Upstream id"); 00293 return -1; 00294 } 00295 00296 ns_list_foreach(nd_proxy_connected_list_s, e, &paired_interface_list) { 00297 00298 if (e->id != upstream_id) { 00299 continue; 00300 } 00301 00302 //Check Downstream 00303 ns_list_foreach_safe(nd_proxy_downstream_interfaces_list_s, mesh, &e->connected_downstream_list) { 00304 if (mesh->id == downstream_id) { 00305 return 0; 00306 } 00307 } 00308 } 00309 00310 //Allocate new Upstream and connection 00311 proxy = proxy_upstream_connection_allocate(upstream_id); 00312 00313 if (!proxy) { 00314 tr_error("Proxy alloc fail"); 00315 return -1; 00316 } 00317 00318 if (!proxy_downstream_conection_allocate(downstream_id, &proxy->connected_downstream_list) ) 00319 { 00320 tr_error("Up<->Down stream connect alloc fail"); 00321 if (ns_list_is_empty(&proxy->connected_downstream_list)) { 00322 //Remove connection from list and free memory 00323 ns_list_remove(&paired_interface_list, proxy); 00324 ns_dyn_mem_free(proxy); 00325 } 00326 return -1; 00327 } 00328 00329 if (downstream_interface->bridge_status_update) { 00330 downstream_interface->bridge_status_update(upstream_id, downstream_id, true); 00331 } 00332 return 0; 00333 } 00334 00335 int nd_proxy_downstream_interface_register(int8_t interface_id, nd_proxy_req_cb *nd_proxy_req, bridge_state_update_cb * bridge_state_update) 00336 { 00337 if (interface_id < 0) { 00338 return -1; 00339 } else if (!nd_proxy_req) { 00340 return -1; 00341 } 00342 nd_proxy_downstream_list_s * entry = proxy_cache_downstream_interface_allocate(interface_id, &downstream_interface_list); 00343 if (!entry) { 00344 return -2; 00345 } 00346 //Set Function pointers 00347 entry->bridge_status_update = bridge_state_update; 00348 entry->nd_proxy_validation = nd_proxy_req; 00349 00350 ns_list_foreach(nd_proxy_upstream_list_s, e, &upstream_interface_list) { 00351 00352 if (proxy_cache_interface_enable_proxy(e->id,interface_id) == 0) { 00353 tr_debug("Proxy bridge enabled for interface %i to %i\n", e->id, interface_id); 00354 } 00355 } 00356 00357 return 0; 00358 } 00359 00360 int nd_proxy_downstream_interface_unregister(int8_t interface_id) 00361 { 00362 //Release from paired 00363 proxy_cache_untie_connection_by_downstream(interface_id); 00364 00365 ns_list_foreach(nd_proxy_downstream_list_s, e, &downstream_interface_list) { 00366 if (e->id == interface_id) { 00367 ns_list_remove(&downstream_interface_list, e); 00368 ns_dyn_mem_free(e); 00369 return 0; 00370 } 00371 } 00372 00373 return -1; 00374 } 00375 00376 int nd_proxy_upstream_interface_register(int8_t interface_id, nd_proxy_req_cb *route_validation_req) 00377 { 00378 if (interface_id < 0) { 00379 return -1; 00380 } else if (!route_validation_req) { 00381 return -1; 00382 } 00383 00384 nd_proxy_upstream_list_s * entry = proxy_cache_upstream_interface_allocate(interface_id, &upstream_interface_list); 00385 if (!entry) { 00386 return -1; 00387 } 00388 //Set Function pointers 00389 entry->route_on_link_validation = route_validation_req; 00390 00391 //Link now all available interfaces which give proxy service 00392 ns_list_foreach(nd_proxy_downstream_list_s, e, &downstream_interface_list) { 00393 00394 if (proxy_cache_interface_enable_proxy(interface_id, e->id) == 0) { 00395 tr_debug("Proxy bridge enabled for interface %i to %i \n", interface_id, e->id); 00396 } 00397 } 00398 return 0; 00399 } 00400 00401 int nd_proxy_upstream_interface_unregister(int8_t interface_id) 00402 { 00403 proxy_cache_untie_connection_by_upstream(interface_id); 00404 00405 ns_list_foreach(nd_proxy_upstream_list_s, e, &upstream_interface_list) { 00406 if (e->id == interface_id) { 00407 ns_list_remove(&upstream_interface_list, e); 00408 ns_dyn_mem_free(e); 00409 return 0; 00410 } 00411 } 00412 00413 return -1; 00414 } 00415 00416 bool nd_proxy_enabled_for_downstream(int8_t interface_id) 00417 { 00418 if (proxy_upstream_conection_get(interface_id) ) { 00419 return true; 00420 } 00421 return false; 00422 } 00423 00424 bool nd_proxy_enabled_for_upstream(int8_t interface_id) 00425 { 00426 ns_list_foreach(nd_proxy_connected_list_s, e, &paired_interface_list) { 00427 00428 ns_list_foreach(nd_proxy_downstream_interfaces_list_s, mesh, &e->connected_downstream_list) { 00429 if (mesh->id == interface_id) { 00430 return true; 00431 } 00432 } 00433 } 00434 return false; 00435 } 00436 00437 bool nd_proxy_target_address_validation(int8_t upstream_id, uint8_t *address, int8_t *downstream_id_ptr) 00438 { 00439 nd_proxy_downstream_list_s *downstream; 00440 nd_proxy_connected_list_s *upstream = proxy_upstream_conection_get(upstream_id); 00441 *downstream_id_ptr = -1; 00442 if (!upstream) { 00443 return false; 00444 } 00445 00446 ns_list_foreach(nd_proxy_downstream_interfaces_list_s, downstream_entry, &upstream->connected_downstream_list) { 00447 downstream = proxy_cache_downstream_interface_get(downstream_entry->id, &downstream_interface_list); 00448 if (downstream) { 00449 if (downstream->nd_proxy_validation(downstream_entry->id, address) == 0) { 00450 *downstream_id_ptr = downstream_entry->id; 00451 return true; 00452 } 00453 } 00454 } 00455 00456 return false; 00457 } 00458 00459 bool nd_proxy_upstream_route_onlink(int8_t downstream_id, uint8_t *address) 00460 { 00461 ns_list_foreach(nd_proxy_connected_list_s, e, &paired_interface_list) { 00462 00463 ns_list_foreach(nd_proxy_downstream_interfaces_list_s, downstream, &e->connected_downstream_list) { 00464 if (downstream->id == downstream_id) { 00465 nd_proxy_upstream_list_s *upstream = proxy_cache_upstream_interface_get(e->id, &upstream_interface_list); 00466 if (upstream) { 00467 if (upstream->route_on_link_validation(e->id, address) == 0) { 00468 return true; 00469 } 00470 } 00471 } 00472 } 00473 } 00474 return false; 00475 } 00476 #endif /* HAVE_ND_PROXY */ 00477
Generated on Tue Jul 12 2022 12:22:13 by
