Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers nd_proxy.c Source File

nd_proxy.c

00001 /*
00002  * Copyright (c) 2015-2018, 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         tr_error("Up<->Down stream connect alloc fail");
00320         if (ns_list_is_empty(&proxy->connected_downstream_list)) {
00321             //Remove connection from list and free memory
00322             ns_list_remove(&paired_interface_list, proxy);
00323             ns_dyn_mem_free(proxy);
00324         }
00325         return -1;
00326     }
00327 
00328     if (downstream_interface->bridge_status_update) {
00329         downstream_interface->bridge_status_update(upstream_id, downstream_id, true);
00330     }
00331     return 0;
00332 }
00333 
00334 int nd_proxy_downstream_interface_register(int8_t interface_id, nd_proxy_req_cb *nd_proxy_req, bridge_state_update_cb *bridge_state_update)
00335 {
00336     if (interface_id < 0) {
00337         return -1;
00338     } else if (!nd_proxy_req) {
00339         return -1;
00340     }
00341     nd_proxy_downstream_list_s *entry = proxy_cache_downstream_interface_allocate(interface_id, &downstream_interface_list);
00342     if (!entry) {
00343         return -2;
00344     }
00345     //Set Function pointers
00346     entry->bridge_status_update = bridge_state_update;
00347     entry->nd_proxy_validation = nd_proxy_req;
00348 
00349     ns_list_foreach(nd_proxy_upstream_list_s, e, &upstream_interface_list) {
00350 
00351         if (proxy_cache_interface_enable_proxy(e->id, interface_id) == 0) {
00352             tr_debug("Proxy bridge enabled for interface %i to %i\n", e->id, interface_id);
00353         }
00354     }
00355 
00356     return 0;
00357 }
00358 
00359 int nd_proxy_downstream_interface_unregister(int8_t interface_id)
00360 {
00361     //Release from paired
00362     proxy_cache_untie_connection_by_downstream(interface_id);
00363 
00364     ns_list_foreach(nd_proxy_downstream_list_s, e, &downstream_interface_list) {
00365         if (e->id == interface_id) {
00366             ns_list_remove(&downstream_interface_list, e);
00367             ns_dyn_mem_free(e);
00368             return 0;
00369         }
00370     }
00371 
00372     return -1;
00373 }
00374 
00375 int nd_proxy_upstream_interface_register(int8_t interface_id, nd_proxy_req_cb *route_validation_req)
00376 {
00377     if (interface_id < 0) {
00378         return -1;
00379     } else if (!route_validation_req) {
00380         return -1;
00381     }
00382 
00383     nd_proxy_upstream_list_s *entry = proxy_cache_upstream_interface_allocate(interface_id, &upstream_interface_list);
00384     if (!entry) {
00385         return -1;
00386     }
00387     //Set Function pointers
00388     entry->route_on_link_validation = route_validation_req;
00389 
00390     //Link now all available interfaces which give proxy service
00391     ns_list_foreach(nd_proxy_downstream_list_s, e, &downstream_interface_list) {
00392 
00393         if (proxy_cache_interface_enable_proxy(interface_id, e->id) == 0) {
00394             tr_debug("Proxy bridge enabled for interface %i to %i \n", interface_id, e->id);
00395         }
00396     }
00397     return 0;
00398 }
00399 
00400 int nd_proxy_upstream_interface_unregister(int8_t interface_id)
00401 {
00402     proxy_cache_untie_connection_by_upstream(interface_id);
00403 
00404     ns_list_foreach(nd_proxy_upstream_list_s, e, &upstream_interface_list) {
00405         if (e->id == interface_id) {
00406             ns_list_remove(&upstream_interface_list, e);
00407             ns_dyn_mem_free(e);
00408             return 0;
00409         }
00410     }
00411 
00412     return -1;
00413 }
00414 
00415 bool nd_proxy_enabled_for_downstream(int8_t interface_id)
00416 {
00417     if (proxy_upstream_conection_get(interface_id)) {
00418         return true;
00419     }
00420     return false;
00421 }
00422 
00423 bool nd_proxy_enabled_for_upstream(int8_t interface_id)
00424 {
00425     ns_list_foreach(nd_proxy_connected_list_s, e, &paired_interface_list) {
00426 
00427         ns_list_foreach(nd_proxy_downstream_interfaces_list_s, mesh, &e->connected_downstream_list) {
00428             if (mesh->id == interface_id) {
00429                 return true;
00430             }
00431         }
00432     }
00433     return false;
00434 }
00435 
00436 bool nd_proxy_target_address_validation(int8_t upstream_id, uint8_t *address)
00437 {
00438     nd_proxy_downstream_list_s *downstream;
00439     nd_proxy_connected_list_s *upstream = proxy_upstream_conection_get(upstream_id);
00440 
00441     if (!upstream) {
00442         return false;
00443     }
00444 
00445     ns_list_foreach(nd_proxy_downstream_interfaces_list_s, downstream_entry, &upstream->connected_downstream_list) {
00446         downstream = proxy_cache_downstream_interface_get(downstream_entry->id, &downstream_interface_list);
00447         if (downstream) {
00448             if (downstream->nd_proxy_validation(downstream_entry->id, address) == 0) {
00449                 return true;
00450             }
00451         }
00452     }
00453 
00454     return false;
00455 }
00456 
00457 bool nd_proxy_upstream_route_onlink(int8_t downstream_id, uint8_t *address)
00458 {
00459     ns_list_foreach(nd_proxy_connected_list_s, e, &paired_interface_list) {
00460 
00461         ns_list_foreach(nd_proxy_downstream_interfaces_list_s, downstream, &e->connected_downstream_list) {
00462             if (downstream->id == downstream_id) {
00463                 nd_proxy_upstream_list_s *upstream = proxy_cache_upstream_interface_get(e->id, &upstream_interface_list);
00464                 if (upstream) {
00465                     if (upstream->route_on_link_validation(e->id, address) == 0) {
00466                         return true;
00467                     }
00468                 }
00469             }
00470         }
00471     }
00472     return false;
00473 }
00474 #endif /* HAVE_ND_PROXY */
00475