Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ns_net.c Source File

ns_net.c

00001 /*
00002  * Copyright (c) 2014-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  * \file net.c
00019  * \brief Network API for library model
00020  *
00021  * The network API functions for library model
00022  */
00023 #include "nsconfig.h"
00024 #include "ns_types.h"
00025 #include "eventOS_scheduler.h"
00026 #include "string.h"
00027 #include "ns_trace.h"
00028 #include "socket_api.h"
00029 #include "nsdynmemLIB.h"
00030 #include "NWK_INTERFACE/Include/protocol.h"
00031 #include "Core/include/ns_socket.h"
00032 #ifdef HAVE_RPL
00033 #include "RPL/rpl_of0.h"
00034 #include "RPL/rpl_mrhof.h"
00035 #include "RPL/rpl_control.h"
00036 #include "RPL/rpl_data.h"
00037 #endif
00038 #include "ccmLIB.h"
00039 #include "6LoWPAN/lowpan_adaptation_interface.h"
00040 #include "6LoWPAN/Bootstraps/network_lib.h"
00041 #include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
00042 #include "6LoWPAN/Bootstraps/protocol_6lowpan_bootstrap.h"
00043 #include "6LoWPAN/ND/nd_router_object.h"
00044 #include "6LoWPAN/MAC/mac_helper.h"
00045 #include "6LoWPAN/MAC/beacon_handler.h"
00046 #ifndef NO_MLE
00047 #include "MLE/mle.h"
00048 #endif
00049 #include "platform/arm_hal_interrupt.h"
00050 #include "common_functions.h"
00051 #include "Service_Libs/whiteboard/whiteboard.h"
00052 #include "net_pana_parameters_api.h"
00053 #ifdef ECC
00054 #include "libX509_V3.h"
00055 #include "ecc.h"
00056 #endif
00057 #include "Security/PANA/pana.h"
00058 #include "Security/PANA/pana_internal_api.h"
00059 #include "nwk_stats_api.h"
00060 #include "NWK_INTERFACE/Include/protocol_stats.h"
00061 #include "Security/Common/sec_lib_definitions.h"
00062 #include "ipv6_stack/protocol_ipv6.h"
00063 #include "ipv6_stack/ipv6_routing_table.h"
00064 #include "net_thread_test.h"
00065 #include "6LoWPAN/Thread/thread_common.h"
00066 #include "6LoWPAN/Thread/thread_routing.h"
00067 #include "6LoWPAN/Thread/thread_bootstrap.h"
00068 #include "6LoWPAN/Thread/thread_management_internal.h"
00069 #include "6LoWPAN/ws/ws_bootstrap.h"
00070 #ifdef HAVE_WS
00071 #include "6LoWPAN/ws/ws_pae_controller.h"
00072 #endif
00073 #include "BorderRouter/border_router.h"
00074 #include "Service_Libs/mle_service/mle_service_api.h"
00075 #include "6LoWPAN/MAC/mac_data_poll.h"
00076 #include "sw_mac.h"
00077 #include "mac_api.h"
00078 #include "ethernet_mac_api.h"
00079 #include <stdarg.h>
00080 
00081 
00082 #define TRACE_GROUP "lNet"
00083 /**
00084  * \brief A function checks that the channel list is not empty. Channel pages 9 and 10 can have eight 32-bit channel masks.
00085  * \param scan_list is a pointer to the channel list structure given by the application.
00086  * \return 0 on success.
00087  * \return -1 if channel list is empty.
00088  */
00089 static int arm_channel_list_validation(const channel_list_s *scan_list)
00090 {
00091     uint8_t i = 1;
00092     if (scan_list) {
00093         if (scan_list->channel_page == CHANNEL_PAGE_9 || scan_list->channel_page == CHANNEL_PAGE_10) {
00094             i = 8;
00095         }
00096         while (i--)
00097             if (scan_list->channel_mask[i]) {
00098                 return 0;
00099             }
00100     }
00101     return -1;
00102 }
00103 
00104 
00105 /* Energy & Active Scan API */
00106 int8_t arm_net_energy_scan(int8_t interface_id, channel_list_s *scan_list, void (*passed_fptr)(int8_t if_id, const mlme_scan_conf_t *conf), uint8_t energy_tresshold)
00107 {
00108     (void)interface_id;
00109     (void)scan_list;
00110     (void)passed_fptr;
00111     (void)energy_tresshold;
00112     int8_t ret_val = -3;
00113 #ifdef HAVE_RF_TUNNEL
00114     (void)interface_id;
00115     (void)scan_list;
00116     (void)passed_fptr;
00117     (void)energy_tresshold;
00118 #else
00119     protocol_interface_info_entry_t *cur = 0;
00120     cur = protocol_stack_interface_info_get_by_id(interface_id);
00121     if (cur) {
00122         if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
00123             ret_val = -1;
00124         } else {
00125 
00126             nwk_scan_params_t *scan_params = 0;
00127             if (cur->mac_parameters) {
00128                 scan_params = &cur->mac_parameters->nwk_scan_params;
00129                 scan_params->stack_chan_list = *scan_list;
00130                 scan_params->energy_treshold = energy_tresshold;
00131 
00132                 mlme_scan_t req;
00133                 mac_create_scan_request(MAC_ED_SCAN_TYPE, &cur->mac_parameters->nwk_scan_params.stack_chan_list, 5, &req);
00134                 if (cur->mac_api) {
00135                     cur->scan_cb = passed_fptr;
00136                     cur->mac_api->mlme_req(cur->mac_api, MLME_SCAN, &req);
00137                     ret_val = 0;
00138                 }
00139             }
00140         }
00141     }
00142 #endif
00143     return ret_val;
00144 
00145 }
00146 
00147 int8_t arm_net_nwk_scan(int8_t interface_id, channel_list_s *scan_list, void (*passed_fptr)(int8_t if_id, const mlme_scan_conf_t *conf), uint8_t scan_level)
00148 {
00149     (void)interface_id;
00150     (void)scan_list;
00151     (void)passed_fptr;
00152     (void)scan_level;
00153     int8_t ret_val = -3;
00154 #ifdef HAVE_RF_TUNNEL
00155     (void)interface_id;
00156     (void)scan_list;
00157     (void)passed_fptr;
00158     (void)scan_level;
00159 #else
00160     protocol_interface_info_entry_t *cur = 0;
00161     cur = protocol_stack_interface_info_get_by_id(interface_id);
00162 
00163     if (cur) {
00164         cur->scan_cb = passed_fptr;
00165         if (cur->mac_parameters) {
00166             nwk_filter_params_s *filter = &(cur->mac_parameters->nwk_filter_params);
00167             if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
00168                 ret_val = -1;
00169             } else if (arm_channel_list_validation(scan_list)) {
00170                 tr_debug("Given channel mask is empty!\n");
00171                 ret_val = -2;
00172             } else {
00173                 nwk_scan_params_t *scan_params = &cur->mac_parameters->nwk_scan_params;
00174                 scan_params->stack_chan_list = *scan_list;
00175 
00176                 mlme_scan_t req;
00177                 mac_create_scan_request(MAC_ACTIVE_SCAN, &scan_params->stack_chan_list, 5, &req);
00178                 if (cur->mac_api) {
00179                     cur->scan_cb = passed_fptr;
00180                     scan_params->active_scan_active = true;
00181                     cur->mac_api->mlme_req(cur->mac_api, MLME_SCAN, &req);
00182                 }
00183                 filter->nwk_active_scan_level = scan_level;
00184                 mac_helper_nwk_id_filter_set(0, filter);
00185                 mac_helper_mac16_address_set(cur, 0xffff);
00186                 protocol_6lowpan_register_handlers(cur);
00187                 ret_val = 0;
00188 
00189             }
00190         }
00191     }
00192 #endif
00193     return ret_val;
00194 }
00195 
00196 nwk_pan_descriptor_t *arm_net_get_scanned_nwk_list(int8_t interface_id)
00197 {
00198     nwk_pan_descriptor_t *ret_val = 0;
00199     protocol_interface_info_entry_t *cur = 0;
00200     cur = protocol_stack_interface_info_get_by_id(interface_id);
00201     if (cur) {
00202         if (cur->mac_parameters) {
00203             ret_val = cur->mac_parameters->nwk_scan_params.nwk_response_info;
00204         }
00205     }
00206     return ret_val;
00207 }
00208 
00209 /**
00210  * \brief A function to read pan ID filter.
00211  * \return 16-bit value indicating a pan ID filter.
00212  */
00213 uint16_t arm_net_get_nwk_pan_id_filter(int8_t interface_id)
00214 {
00215     protocol_interface_info_entry_t *cur = 0;
00216     cur = protocol_stack_interface_info_get_by_id(interface_id);
00217     if (cur) {
00218         if (cur->mac_parameters) {
00219             nwk_filter_params_s *filter = &(cur->mac_parameters->nwk_filter_params);
00220             return filter->net_pan_id_filter;
00221         }
00222     }
00223     return 0;
00224 }
00225 
00226 /**
00227  * \brief A function to read network layer configurations.
00228  * \param network_params is a pointer to the structure to where the network layer configs are written to.
00229  * \return 0 on success.
00230  * \return Negative value if interface id or PAN coordinator is not known.
00231  */
00232 int8_t arm_nwk_param_read(int8_t interface_id, link_layer_setups_s *network_params)
00233 {
00234     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00235     addrtype_t addrType = mac_helper_coordinator_address_get(cur, network_params->address);
00236     if (addrType == ADDR_NONE ) {
00237         return -2;
00238     }
00239     network_params->PANId = mac_helper_panid_get(cur);
00240     if (addrType == ADDR_802_15_4_SHORT ) {
00241         network_params->addr_mode = ADDR_MAC_SHORT16;
00242     } else {
00243         network_params->addr_mode = ADDR_MAC_LONG64;
00244     }
00245 
00246     network_params->LogicalChannel = cur->mac_parameters->mac_channel;
00247     network_params->sf = 0xff;
00248     return 0;
00249 }
00250 
00251 /**
00252  * \brief A function to read MAC PAN-ID, Short address & EUID64
00253  * \param mac_params is a pointer to the structure to where the mac address are written to.
00254  * \return 0 on success.
00255  * \return Negative value if interface id is not known.
00256  */
00257 int8_t arm_nwk_mac_address_read(int8_t interface_id, link_layer_address_s *mac_params)
00258 {
00259     int8_t ret_val = -2;
00260     protocol_interface_info_entry_t *cur = 0;
00261     cur = protocol_stack_interface_info_get_by_id(interface_id);
00262     if (cur) {
00263         ret_val = 0;
00264         memcpy(mac_params->mac_long, cur->mac, 8);
00265         memcpy(mac_params->iid_eui64, cur->iid_eui64, 8);
00266         if (cur->mac_parameters) {
00267             mac_params->PANId = cur->mac_parameters->pan_id;
00268             mac_params->mac_short = cur->mac_parameters->mac_short_address;
00269         } else {
00270             mac_params->PANId = 0xffff;
00271             mac_params->mac_short = 0xffff;
00272         }
00273     }
00274     return ret_val;
00275 }
00276 
00277 /**
00278  * \brief A function to read 6LoWPAN ND border router address and NWK prefix
00279  * \param mac_params is a pointer to the structure to where the mac address are written to.
00280  * \return 0 on success.
00281  * \return -1 .
00282  */
00283 int8_t arm_nwk_nd_address_read(int8_t interface_id, network_layer_address_s *nd_addr_info)
00284 {
00285     (void)interface_id;
00286     (void)nd_addr_info;
00287     int8_t ret_val = -2;
00288 #ifdef HAVE_6LOWPAN_ND
00289     protocol_interface_info_entry_t *cur = 0;
00290     cur = protocol_stack_interface_info_get_by_id(interface_id);
00291     if (cur) {
00292         if ((cur->lowpan_info & (INTERFACE_NWK_ACTIVE | INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY)) == (INTERFACE_NWK_ACTIVE | INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY)) {
00293             uint8_t *adr_ptr = protocol_6lowpan_nd_border_router_address_get(cur->nwk_id);
00294             if (adr_ptr) {
00295                 ret_val = 0;
00296                 memcpy(nd_addr_info->border_router, adr_ptr, 16);
00297                 memcpy(nd_addr_info->prefix, adr_ptr, 8);
00298             }
00299         }
00300     }
00301 #else
00302     (void)interface_id;
00303     (void)nd_addr_info;
00304 #endif
00305     return ret_val;
00306 }
00307 
00308 /**
00309   * \brief Get current used channel.
00310   *
00311   * \return Active channel
00312   * \return -1 if invalid network interface ID is given
00313   */
00314 int16_t arm_net_get_current_channel(int8_t interface_id)
00315 {
00316     int16_t ret_val = -1;
00317     protocol_interface_info_entry_t *cur = 0;
00318     cur = protocol_stack_interface_info_get_by_id(interface_id);
00319     if (cur) {
00320         if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
00321             ret_val = cur->mac_parameters->mac_channel;
00322         }
00323     }
00324 
00325     return ret_val;
00326 }
00327 
00328 /**
00329  * \brief A function to set sleep mode of a host.
00330  * \param state equals to 1 if the sleep mode is to be enabled, 0 if the sleep mode is to be disabled.
00331  */
00332 void arm_net_host_enter_sleep_state_set(int8_t interface_id, uint8_t state)
00333 {
00334     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00335     if (cur && cur->rfd_poll_info) {
00336 
00337         if (state) {
00338             cur->rfd_poll_info->macDeepSleepEnabled = true;
00339         } else {
00340             cur->rfd_poll_info->macDeepSleepEnabled = false;
00341         }
00342     }
00343 }
00344 
00345 
00346 /**
00347  * \brief A function to read library version information.
00348  * \param ptr is a pointer to an array to where the version information is read to.
00349  */
00350 void net_get_version_information(uint8_t *ptr)
00351 {
00352     (void)ptr;
00353 }
00354 
00355 /**
00356  * \brief Set configured network interface Global address mode (Border router bootstrap mode can't set this).
00357  *
00358  * \param interface_id Network interface ID
00359  * \param mode efine 6LoWPAN Global Address register mode::
00360  *      * NET_6LOWPAN_GP64_ADDRESS, Interface register only GP64
00361  *      * NET_6LOWPAN_GP16_ADDRESS, Interface register only GP16
00362  *      * NET_6LOWPAN_MULTI_GP_ADDRESS, Interface register GP16 and GP64 addresses. GP16 is primary address and GP64 is secondary.
00363  *
00364  * \param short_address_base Short address base. If application defines value 0-0xfffd 6LoWPAN try to register GP16 address using that address. 0xfffe and 0xffff will generate random 16-bit short address.
00365  *
00366  * \param define_new_short_address_at_DAD This parameter is only checked when mode is not NET_6LOWPAN_GP64_ADDRESS and short_address_base is 0-0xfffd. Recommend value is 1 that will enable automatic new address definition at Duplicate Address Detection(DAD). Value 0 will generate Duplicate Adreress Detection error for interface bootstrap.
00367 Border Router Device will not check that part.
00368  *
00369  * \return >=0 Bootstrap mode set OK.
00370  * \return -1 Unknown network ID.
00371  * \return -2 Illegal for Border Router
00372  * \return -3 Bootsrap not defined yet.
00373  */
00374 int8_t arm_nwk_6lowpan_gp_address_mode(int8_t interface_id, net_6lowpan_gp_address_mode_e mode, uint16_t short_address_base, uint8_t define_new_short_address_at_DAD)
00375 {
00376 #ifdef HAVE_6LOWPAN_ND
00377     protocol_interface_info_entry_t *cur;
00378     cur = protocol_stack_interface_info_get_by_id(interface_id);
00379     if (!cur) {
00380         return -1;
00381     }
00382     if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
00383         return -2;
00384     }
00385     if (!(cur->configure_flags & INTERFACE_BOOTSTRAP_DEFINED)) {
00386         return -3;
00387     }
00388 
00389     if (thread_info(cur)) {
00390         return -2;
00391     }
00392 
00393     if (short_address_base < 0xfffe) {
00394         cur->lowpan_desired_short_address = short_address_base;
00395     } else {
00396         protocol_6lowpan_allocate_mac16(cur); //Allocate Random init value
00397     }
00398     cur->reallocate_short_address_if_duplicate = define_new_short_address_at_DAD;
00399     cur->lowpan_address_mode = mode;
00400 
00401     return 0;
00402 #else
00403     return -2;
00404 #endif
00405 }
00406 
00407 /**
00408  * \brief A function to read networking address informations.
00409  * \param addr_id identifies the address information type to be read.
00410  * \param address is a pointer to a buffer to where the address information is written to.
00411  * \return zero on success, -1 on errors.
00412  */
00413 int8_t arm_net_address_get(int8_t interface_id, net_address_t addr_id, uint8_t *address)
00414 {
00415     int8_t ret_val = -1;
00416     protocol_interface_info_entry_t *cur;
00417     const uint8_t *addr;
00418 
00419     cur = protocol_stack_interface_info_get_by_id(interface_id);
00420     if (!cur) {
00421         return -1;
00422     }
00423 
00424     if (!cur->global_address_available) { //Should also check Check Bootstrap state
00425         return -1;
00426     }
00427 
00428     switch (addr_id) {
00429         case ADDR_IPV6_LL:
00430             ret_val = addr_interface_get_ll_address(cur, address, 0);
00431             break;
00432 
00433         case ADDR_IPV6_GP:
00434             addr = addr_select_with_prefix(cur, NULL, 0, SOCKET_IPV6_PREFER_SRC_PUBLIC | SOCKET_IPV6_PREFER_SRC_6LOWPAN_SHORT);
00435             if (addr) {
00436                 memcpy(address, addr, 16);
00437                 ret_val = 0;
00438             }
00439             break;
00440 
00441         case ADDR_IPV6_GP_SEC:
00442             addr = addr_select_with_prefix(cur, NULL, 0, SOCKET_IPV6_PREFER_SRC_PUBLIC | SOCKET_IPV6_PREFER_SRC_6LOWPAN_LONG);
00443             /* Return if the "prefer long" gives a different answer to the default "prefer short". Pointer comparison is
00444              * sufficient as addr_select returns a pointer into the address list. */
00445             if (addr && addr != addr_select_with_prefix(cur, NULL, 0, SOCKET_IPV6_PREFER_SRC_PUBLIC | SOCKET_IPV6_PREFER_SRC_6LOWPAN_SHORT)) {
00446                 memcpy(address, addr, 16);
00447                 ret_val = 0;
00448             }
00449             break;
00450     }
00451     return ret_val;
00452 }
00453 
00454 /**
00455  * \brief A function to read network Interface address count.
00456  * \param interface_id Id to interface.
00457  * \param address_count Pointer where address count will be saved.
00458  * \return zero on success, -1 on errors.
00459  */
00460 int8_t arm_net_interface_address_list_size(int8_t interface_id, uint16_t *address_count)
00461 {
00462     int8_t ret_val = -1;
00463     protocol_interface_info_entry_t *cur;
00464     *address_count = 0;
00465     cur = protocol_stack_interface_info_get_by_id(interface_id);
00466     if (cur) {
00467         ns_list_foreach(if_address_entry_t, addr, &cur->ip_addresses) {
00468             if (!addr->tentative) {
00469                 (*address_count)++;
00470             }
00471         }
00472 
00473         ret_val = 0;
00474     }
00475     return ret_val;
00476 }
00477 
00478 /**
00479  * \brief A function to set interface metric.
00480  * \param interface_id Network interface ID.
00481  * \param metric Used to rank otherwise-equivalent routes. Lower is preferred and default is 0. The metric value is added to metric provided by the arm_net_route_add() function.
00482  * \return 0 On success, -1 on errors.
00483  */
00484 int8_t arm_net_interface_set_metric(int8_t interface_id, uint16_t metric)
00485 {
00486     int8_t ret_val = -1;
00487     protocol_interface_info_entry_t *cur;
00488     cur = protocol_stack_interface_info_get_by_id(interface_id);
00489 
00490     if (cur) {
00491         cur->ipv6_neighbour_cache.route_if_info.metric = metric;
00492         ret_val = 0;
00493     }
00494 
00495     return ret_val;
00496 }
00497 
00498 /**
00499  * \brief A function to read the interface metric value on an interface.
00500  * \param interface_id Network interface ID.
00501  * \param metric A pointer to the variable where the interface metric value is saved.
00502  * \return 0 On success, -1 on errors.
00503  */
00504 int8_t arm_net_interface_get_metric(int8_t interface_id, uint16_t *metric)
00505 {
00506     int8_t ret_val = -1;
00507     protocol_interface_info_entry_t *cur;
00508     cur = protocol_stack_interface_info_get_by_id(interface_id);
00509 
00510     if (cur) {
00511         *metric = cur->ipv6_neighbour_cache.route_if_info.metric;
00512         ret_val = 0;
00513     }
00514 
00515     return ret_val;
00516 }
00517 
00518 /**
00519  * \brief A function to read network Interface.
00520  * \param interface_id Id to interface.
00521  * \param address_buf_size Indicate buffer size in bytes minimal is 16 bytes.
00522  * \param address_buffer pointer where stack save address one by one.
00523  * \param writed_address_count pointer where stack save how many address is writed behind address_buffer.
00524  *
00525  * \return zero on success, -1 on errors.
00526  */
00527 int8_t arm_net_address_list_get(int8_t interface_id, uint8_t address_buf_size, uint8_t *address_buffer, int *writed_address_count)
00528 {
00529     int8_t ret_val = -1;
00530     protocol_interface_info_entry_t *cur;
00531     int address_count = 0;
00532 
00533 
00534     cur = protocol_stack_interface_info_get_by_id(interface_id);
00535     if (!cur) {
00536         return -1;
00537     }
00538 
00539     if (address_buf_size >= 16) {
00540         int loop_counter = 0;
00541         bool save_address;
00542         while (loop_counter < 2) {
00543             ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) {
00544                 if (e->tentative) {
00545                     continue;
00546                 }
00547 
00548                 save_address = false;
00549                 if (loop_counter) {
00550                     if (!addr_is_ipv6_link_local(e->address)) {
00551                         save_address = true;
00552                     }
00553                 } else {
00554                     if (addr_is_ipv6_link_local(e->address)) {
00555                         save_address = true;
00556                     }
00557                 }
00558                 if (save_address) {
00559                     memcpy(address_buffer, e->address, 16);
00560                     address_buf_size -= 16;
00561                     ret_val = 0;
00562                     address_count++;
00563                     if (address_buf_size >= 16) {
00564                         address_buffer += 16;
00565                     } else {
00566                         *writed_address_count = address_count;
00567                         return ret_val;
00568                     }
00569                 }
00570             }
00571             loop_counter++;
00572         }
00573         //Save writed address count to Pointer
00574         *writed_address_count = address_count;
00575     }
00576     return ret_val;
00577 }
00578 
00579 int8_t arm_net_address_list_get_next(int8_t interface_id, int *n, uint8_t address_buffer[16])
00580 {
00581     int8_t ret_val = -1;
00582     protocol_interface_info_entry_t *cur;
00583     int address_count = 0;
00584 
00585     cur = protocol_stack_interface_info_get_by_id(interface_id);
00586     if (!cur) {
00587         return -1;
00588     }
00589 
00590     int loop_counter = 0;
00591     bool save_address;
00592     while (loop_counter < 2) {
00593         ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) {
00594             if (e->tentative) {
00595                 continue;
00596             }
00597 
00598             save_address = false;
00599             if (loop_counter) {
00600                 if (!addr_is_ipv6_link_local(e->address)) {
00601                     save_address = true;
00602                 }
00603             } else {
00604                 if (addr_is_ipv6_link_local(e->address)) {
00605                     save_address = true;
00606                 }
00607             }
00608             if (save_address) {
00609                 if (*n == address_count) {
00610                     memcpy(address_buffer, e->address, 16);
00611                     *n = *n + 1;
00612                     return 0;
00613                 }
00614                 address_count++;
00615             }
00616         }
00617         loop_counter++;
00618     }
00619     return ret_val;
00620 }
00621 
00622 int8_t arm_net_address_add_to_interface(int8_t interface_id, const uint8_t address[16], uint8_t prefix_len, uint32_t valid_lifetime, uint32_t preferred_lifetime)
00623 {
00624     protocol_interface_info_entry_t *cur;
00625     if_address_entry_t *entry;
00626 
00627     cur = protocol_stack_interface_info_get_by_id(interface_id);
00628 
00629     if (!cur) {
00630         return -1;
00631     }
00632 
00633     entry = addr_add(cur, address, prefix_len, ADDR_SOURCE_STATIC, valid_lifetime, preferred_lifetime, false);
00634 
00635     if (!entry) {
00636         return -1;
00637     }
00638 
00639     return 0;
00640 }
00641 
00642 int8_t arm_net_address_delete_from_interface(int8_t interface_id, const uint8_t address[16])
00643 {
00644     protocol_interface_info_entry_t *cur;
00645     cur = protocol_stack_interface_info_get_by_id(interface_id);
00646 
00647     if (!cur) {
00648         return -1;
00649     }
00650 
00651     return addr_delete(cur, address);
00652 }
00653 
00654 int8_t arm_net_route_add(const uint8_t *prefix, uint8_t prefix_len, const uint8_t *next_hop, uint32_t lifetime, uint8_t metric, int8_t interface_id)
00655 {
00656     ipv6_route_t *entry;
00657 
00658     if (prefix_len > 128 || (prefix == NULL && prefix_len != 0)) {
00659         return -2;
00660     }
00661 
00662     entry = ipv6_route_add_metric(prefix, prefix_len, interface_id, next_hop, ROUTE_USER, NULL, 0, lifetime, metric);
00663 
00664     if (!entry) {
00665         return -1;
00666     }
00667 
00668     return 0;
00669 }
00670 
00671 int8_t arm_net_route_delete(const uint8_t *prefix, uint8_t prefix_len, const uint8_t *next_hop, int8_t interface_id)
00672 {
00673     if (prefix_len > 128 || (prefix == NULL && prefix_len != 0)) {
00674         return -2;
00675     }
00676 
00677     return ipv6_route_delete(prefix, prefix_len, interface_id, next_hop, ROUTE_USER);
00678 }
00679 
00680 
00681 int8_t arm_nwk_interface_ethernet_init(eth_mac_api_t *api, const char *interface_name_ptr)
00682 {
00683 #ifdef HAVE_ETHERNET
00684     if (!api) {
00685         return -1;
00686     }
00687 
00688     protocol_interface_info_entry_t *cur = protocol_stack_interface_generate_ethernet(api);
00689     if (!cur) {
00690         return -3;
00691     }
00692 
00693     cur->if_up = ipv6_interface_up;
00694     cur->if_down = ipv6_interface_down;
00695     cur->interface_name = interface_name_ptr;
00696     return cur->id;
00697 #else
00698     (void)api;
00699     (void)interface_name_ptr;
00700     return -2;
00701 #endif
00702 }
00703 
00704 extern int8_t arm_nwk_interface_ppp_init(struct eth_mac_api_s *api, const char *interface_name_ptr)
00705 {
00706 #ifdef HAVE_ETHERNET
00707     if (!api) {
00708         return -1;
00709     }
00710 
00711     protocol_interface_info_entry_t *cur = protocol_stack_interface_generate_ppp(api);
00712     if (!cur) {
00713         return -3;
00714     }
00715 
00716     cur->if_up = ipv6_interface_up;
00717     cur->if_down = ipv6_interface_down;
00718     cur->interface_name = interface_name_ptr;
00719     return cur->id;
00720 #else
00721     (void)api;
00722     (void)interface_name_ptr;
00723     return -2;
00724 #endif
00725 }
00726 
00727 int8_t arm_nwk_interface_lowpan_init(mac_api_t *api, char *interface_name_ptr)
00728 {
00729     if (!api) {
00730         return -1;
00731     }
00732 
00733     protocol_interface_info_entry_t *cur = protocol_stack_interface_generate_lowpan(api);
00734     if (!cur) {
00735         return -3;
00736     }
00737     protocol_6lowpan_configure_core(cur);
00738     cur->interface_name = interface_name_ptr;
00739     return cur->id;
00740 }
00741 
00742 static int arm_net_channel_bit_mask_to_number(const uint32_t *channel_mask)
00743 {
00744     int i, j;
00745 
00746     for (j = 0; j < 8; j++) {
00747         for (i = 0; i < 32; i++) {
00748             if (channel_mask[j] & ((uint32_t)1 << i)) {
00749                 break;
00750             }
00751         }
00752         if (i < 32) {
00753             break;
00754         }
00755     }
00756     if (j > 7) {
00757         return -1;
00758     }
00759     return i + (j * 32);
00760 }
00761 
00762 /**
00763  * \brief Set network interface link layer parameters.
00764  *
00765  * \param interface_id Network interface ID
00766  * \param tun_driver_id Driver id FOR PHY data IN & OUT
00767  * \param channel define network link channel
00768  * \param link_setup Link layer parameters for NET_6LOWPAN_NETWORK_DRIVER defines NetworkID, PAN-ID Short Address
00769  *
00770 
00771  * \return >=0 Config set OK.
00772  * \return -1 Unknown network ID or tun driver.
00773  * \return -2 Interface is active, Bootsrap mode not selected or is not NET_6LOWPAN_NETWORK_DRIVER or NET_6LOWPAN_SNIFFER.
00774  * \return -3 No Memory for 6LoWPAN stack.
00775  * \return -4 Null pointer parameter
00776  * \return -5 Channel list empty
00777  */
00778 int8_t arm_nwk_interface_network_driver_set(int8_t interface_id, const channel_list_s *nwk_channel_list, network_driver_setup_s *link_setup)
00779 {
00780     int8_t ret_val = -1;
00781     protocol_interface_info_entry_t *cur = 0;
00782 
00783     if (arm_channel_list_validation(nwk_channel_list)) {
00784         tr_debug("Given channel mask is empty!\n");
00785         return -5;
00786     }
00787 
00788     cur = protocol_stack_interface_info_get_by_id(interface_id);
00789     if (!cur || !cur->mac_api) {
00790         return -1;
00791     }
00792 
00793 
00794     if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
00795         ret_val = -2;
00796     } else if ((cur->configure_flags &  INTERFACE_BOOTSTRAP_DEFINED) == 0) {
00797         ret_val = -2;
00798     } else if (link_setup && (link_setup->beacon_payload_tlv_length && link_setup->beacon_payload_tlv_ptr == NULL)) {
00799         ret_val = -4;
00800     } else if (link_setup && (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_RF_ACCESPOINT || cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_RF_SNIFFER)) {
00801 
00802         ret_val = 0;
00803 
00804         if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_RF_ACCESPOINT) {
00805             //Configure setup
00806             uint8_t *beaon_payload = mac_helper_beacon_payload_reallocate(cur, 18);
00807             if (beaon_payload) {
00808                 *beaon_payload++ = link_setup->beacon_protocol_id;
00809                 *beaon_payload++ = 7; //Accept Join / Host & Router
00810                 memcpy(beaon_payload, link_setup->network_id, 16);
00811                 ret_val = mac_helper_beacon_payload_register(cur);
00812             } else {
00813                 ret_val = -3;
00814             }
00815             cur->mac_parameters->mac_channel_list = *nwk_channel_list;
00816         } else {
00817 
00818         }
00819 
00820         if (ret_val == 0) {
00821             if (link_setup->mac_short_adr < 0xfffe) {
00822                 cur->lowpan_address_mode = NET_6LOWPAN_GP16_ADDRESS;
00823             } else {
00824                 cur->lowpan_address_mode = NET_6LOWPAN_GP64_ADDRESS;
00825             }
00826             mac_helper_panid_set(cur, link_setup->mac_panid);
00827             mac_helper_mac16_address_set(cur, link_setup->mac_short_adr);
00828 
00829             int channel_number = arm_net_channel_bit_mask_to_number(nwk_channel_list->channel_mask);
00830 
00831             if (channel_number >= 0) {
00832                 // copy the channel list information, which is needed by FHSS
00833                 //Set Channel
00834                 mac_helper_mac_channel_set(cur, channel_number);
00835                 cur->configure_flags |= INTERFACE_NETWORK_DRIVER_SETUP_DEFINED;
00836             }
00837         } else {
00838             mac_helper_beacon_payload_reallocate(cur, 0);
00839         }
00840     } else {
00841         ret_val = -2;
00842     }
00843     return ret_val;
00844 }
00845 
00846 int8_t arm_nwk_interface_up(int8_t interface_id)
00847 {
00848     int8_t ret_val = -1;
00849     protocol_interface_info_entry_t *cur = 0;
00850     cur = protocol_stack_interface_info_get_by_id(interface_id);
00851     if (!cur) {
00852         return -1;
00853     }
00854 
00855     if ((cur->lowpan_info & INTERFACE_NWK_ACTIVE) && cur->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
00856         return -4;
00857     }
00858 
00859     if (!cur->if_up || !cur->if_down) {
00860         return -5;
00861     }
00862 
00863     cur->net_start_tasklet = eventOS_scheduler_get_active_tasklet();
00864     ret_val = cur->if_up(cur);
00865 
00866 
00867     return ret_val;
00868 }
00869 
00870 int8_t arm_nwk_interface_down(int8_t interface_id)
00871 {
00872 
00873     int8_t ret_val = -1;
00874     protocol_interface_info_entry_t *cur = 0;
00875     cur = protocol_stack_interface_info_get_by_id(interface_id);
00876     if (cur) {
00877 
00878         if (!(cur->lowpan_info & INTERFACE_NWK_ACTIVE)) {
00879             ret_val = -4;
00880         } else if (!cur->if_up || !cur->if_down) {
00881             return -5;
00882         } else {
00883             ret_val = cur->if_down(cur);
00884         }
00885 
00886     }
00887     return ret_val;
00888 }
00889 
00890 int8_t arm_pana_client_key_pull(int8_t interface_id)
00891 {
00892 #ifndef PANA
00893     (void)interface_id;
00894 #endif
00895     return pana_client_key_pull(interface_id);
00896 }
00897 
00898 int8_t arm_nwk_link_layer_security_mode(int8_t interface_id, net_6lowpan_link_layer_sec_mode_e  mode, uint8_t sec_level, const net_link_layer_psk_security_info_s *psk_key_info)
00899 {
00900     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00901     if (!cur || thread_info(cur) || !cur->mac_parameters || (cur->configure_flags & INTERFACE_BOOTSTRAP_DEFINED) == 0) {
00902         return -1;
00903     }
00904 
00905 #ifndef HAVE_6LOWPAN_ND
00906     return -1;
00907 #else
00908     if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
00909         return -4;
00910     }
00911 
00912     //Verify MLE Service
00913     if (arm_6lowpan_mle_service_ready_for_security_init(cur) != 0) {
00914         return -1;
00915     }
00916 
00917     cur->if_lowpan_security_params->nwk_security_mode = mode;
00918     mac_helper_link_frame_counter_set(cur->id, 0); //This is maybe mistake
00919 
00920     if (mode == NET_SEC_MODE_NO_LINK_SECURITY) {
00921         cur->mac_parameters->mac_configured_sec_level = 0;
00922         cur->if_lowpan_security_params->security_level = 0;
00923         cur->configure_flags |= INTERFACE_SECURITY_DEFINED;
00924         cur->lowpan_info &= ~INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION;
00925     } else {
00926         if (sec_level == 0 || sec_level > 7) {
00927             return -2;
00928         }
00929 
00930         cur->mac_parameters->mac_configured_sec_level = sec_level;
00931         cur->if_lowpan_security_params->security_level = sec_level;
00932 
00933         if (mode == NET_SEC_MODE_PSK_LINK_SECURITY) {
00934             if (!psk_key_info) {
00935                 return -2;
00936             }
00937             //SET PSK KEY
00938             cur->if_lowpan_security_params->psk_key_info = *psk_key_info;
00939             cur->lowpan_info &= ~INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION;
00940             cur->configure_flags |= INTERFACE_SECURITY_DEFINED;
00941         } else {
00942             if (!cur->if_lowpan_security_params->pana_params) {
00943                 cur->if_lowpan_security_params->pana_params = pana_client_parameter_allocate();
00944             }
00945 
00946             if (!cur->if_lowpan_security_params->pana_params) {
00947                 return -2;
00948             }
00949             cur->lowpan_info |= (INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION);
00950         }
00951     }
00952     return 0;
00953 #endif
00954 }
00955 
00956 int8_t arm_network_certificate_chain_set(const arm_certificate_chain_entry_s *chain_info)
00957 {
00958 #if !defined(PANA) && !defined(HAVE_WS)
00959     (void)chain_info;
00960 #endif
00961 
00962 #ifdef HAVE_WS
00963     ws_pae_controller_certificate_chain_set(chain_info);
00964 #endif
00965 
00966     return pana_interface_certificate_chain_set(chain_info);
00967 }
00968 
00969 int8_t arm_network_trusted_certificate_add(const arm_certificate_entry_s *cert)
00970 {
00971 #ifdef HAVE_WS
00972     return ws_pae_controller_trusted_certificate_add(cert);
00973 #else
00974     (void) cert;
00975     return -1;
00976 #endif
00977 }
00978 
00979 int8_t arm_network_trusted_certificate_remove(const arm_certificate_entry_s *cert)
00980 {
00981 #ifdef HAVE_WS
00982     return ws_pae_controller_trusted_certificate_remove(cert);
00983 #else
00984     (void) cert;
00985     return -1;
00986 #endif
00987 }
00988 
00989 int8_t arm_network_trusted_certificates_remove(void)
00990 {
00991 #ifdef HAVE_WS
00992     return ws_pae_controller_trusted_certificates_remove();
00993 #else
00994     return -1;
00995 #endif
00996 }
00997 
00998 int8_t arm_network_own_certificate_add(const arm_certificate_entry_s *cert)
00999 {
01000 #ifdef HAVE_WS
01001     return ws_pae_controller_own_certificate_add(cert);
01002 #else
01003     (void) cert;
01004     return -1;
01005 #endif
01006 }
01007 
01008 extern int8_t arm_network_own_certificates_remove(void)
01009 {
01010 #ifdef HAVE_WS
01011     return ws_pae_controller_own_certificates_remove();
01012 #else
01013     return -1;
01014 #endif
01015 }
01016 
01017 int8_t arm_network_certificate_revocation_list_add(const arm_cert_revocation_list_entry_s *crl)
01018 {
01019 #ifdef HAVE_WS
01020     return ws_pae_controller_certificate_revocation_list_add(crl);
01021 #else
01022     (void) crl;
01023     return -1;
01024 #endif
01025 }
01026 
01027 int8_t arm_network_certificate_revocation_list_remove(const arm_cert_revocation_list_entry_s *crl)
01028 {
01029 #ifdef HAVE_WS
01030     return ws_pae_controller_certificate_revocation_list_remove(crl);
01031 #else
01032     (void) crl;
01033     return -1;
01034 #endif
01035 }
01036 
01037 /**
01038  * \brief Read Pana server security key material
01039  *
01040  * previous_active_network_key is information is only valid when current_active_key_index is bigger than 1.
01041  *
01042  *\param key pointer for store keymaterial information.
01043  *
01044  * \return 0 Key Read OK
01045  * \return -1 Pana server key material not available
01046  */
01047 int8_t arm_network_key_get(int8_t interface_id, ns_keys_t *key)
01048 {
01049 #ifndef PANA
01050     (void)interface_id;
01051     (void)key;
01052 #endif
01053     return pana_network_key_get(interface_id, key);
01054 }
01055 
01056 int8_t arm_pana_server_library_init(int8_t interface_id, net_tls_cipher_e cipher_mode, const uint8_t *key_material, uint32_t time_period_before_activate_key)
01057 {
01058 #ifndef PANA
01059     (void)interface_id;
01060     (void)cipher_mode;
01061     (void)key_material;
01062     (void)time_period_before_activate_key;
01063 #endif
01064     return pana_server_interface_init(interface_id, cipher_mode, key_material, time_period_before_activate_key);
01065 }
01066 
01067 int8_t arm_pana_activate_new_key(int8_t interface_id)
01068 {
01069 #ifndef PANA
01070     (void)interface_id;
01071 #endif
01072     return  pana_server_trig_new_key(interface_id);
01073 }
01074 
01075 int8_t arm_pana_server_key_update(int8_t interface_id, const uint8_t *network_key_material)
01076 {
01077 #ifndef PANA
01078     (void)interface_id;
01079     (void)network_key_material;
01080 #endif
01081     return pana_server_key_update(interface_id, network_key_material);
01082 }
01083 
01084 int8_t net_pana_parameter_set(const pana_lib_parameters_s *parameter_ptr)
01085 {
01086 #ifndef PANA
01087     (void)parameter_ptr;
01088 #endif
01089     return pana_set_params(parameter_ptr);
01090 }
01091 
01092 
01093 /**
01094  * \brief API to read PANA library parameters.
01095  *
01096  * \param parameter_ptr Output pointer for Pana parameters
01097  *
01098  */
01099 int8_t net_pana_parameter_read(pana_lib_parameters_s *parameter_ptr)
01100 {
01101 #ifndef PANA
01102     (void)parameter_ptr;
01103 #endif
01104     return pana_get_params(parameter_ptr);
01105 }
01106 
01107 int8_t arm_pana_client_library_init(int8_t interface_id, net_tls_cipher_e cipher_mode, uint32_t psk_key_id)
01108 {
01109 #ifndef PANA
01110     (void)interface_id;
01111     (void)cipher_mode;
01112     (void)psk_key_id;
01113 #endif
01114     return pana_client_interface_init(interface_id, cipher_mode, psk_key_id);
01115 }
01116 
01117 int8_t arm_nwk_interface_configure_ipv6_bootstrap_set(int8_t interface_id, net_ipv6_mode_e bootstrap_mode, const uint8_t *ipv6_prefix_pointer)
01118 {
01119 #ifndef HAVE_ETHERNET
01120     (void)interface_id;
01121     (void)bootstrap_mode;
01122     (void)ipv6_prefix_pointer;
01123 #endif
01124     return ipv6_interface_configure_ipv6_bootstrap_set(interface_id, bootstrap_mode, ipv6_prefix_pointer);
01125 }
01126 
01127 int8_t arm_nwk_interface_accept_ipv6_ra(int8_t interface_id, net_ipv6_accept_ra_e accept_ra)
01128 {
01129 #ifndef HAVE_ETHERNET
01130     (void)interface_id;
01131     (void)accept_ra;
01132 #endif
01133     return ipv6_interface_accept_ra(interface_id, accept_ra);
01134 }
01135 
01136 int8_t arm_6lowpan_bootsrap_set_for_selected_interface(int8_t interface_id)
01137 {
01138     protocol_interface_info_entry_t *cur;
01139 
01140     cur = protocol_stack_interface_info_get_by_id(interface_id);
01141     if (!cur) {
01142         return -1;
01143     }
01144 
01145     if (cur->lowpan_info & INTERFACE_NWK_ACTIVE || cur->interface_mode == INTERFACE_UP) {
01146         return -4;
01147     }
01148 
01149     if (cur->nwk_id != IF_6LoWPAN) {
01150         return -1;
01151     }
01152     return 0;
01153 }
01154 
01155 /**
01156  * \brief Set network interface bootstrap setup.
01157  *
01158  * \param interface_id Network interface ID
01159  * \param bootstrap_mode Selected Bootstrap mode:
01160  *      * NET_6LOWPAN_BORDER_ROUTER, Initialise Border router basic setup
01161  *      * NET_6LOWPAN_ROUTER, Enable normal 6LoWPAN ND and RPL to bootstrap
01162  *      * NET_6LOWPAN_HOST, Enable normal 6LoWPAN ND only to bootstrap
01163  *      * NET_6LOWPAN_SLEEPY_HOST, Enable normal 6LoWPAN ND only to bootstrap
01164  *
01165  * \param net_6lowpan_mode_extension Define MLE protocol use and 6LoWPAN mode
01166  *
01167  * \return >=0 Bootstrap mode set OK.
01168  * \return -1 Unknown network ID.
01169  * \return -2 Unsupported bootstrap type or extension in this library.
01170  * \return -3 No Memory for 6LoWPAN stack.
01171  * \return -4 Null pointer parameter
01172  */
01173 int8_t arm_nwk_interface_configure_6lowpan_bootstrap_set(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode, net_6lowpan_mode_extension_e net_6lowpan_mode_extension)
01174 {
01175     int8_t ret_val;
01176 
01177     ret_val = arm_6lowpan_bootsrap_set_for_selected_interface(interface_id);
01178 
01179     if (ret_val == 0) {
01180 
01181         if (net_6lowpan_mode_extension == NET_6LOWPAN_THREAD) {
01182             ret_val = thread_node_bootstrap_init(interface_id, bootstrap_mode);
01183         } else if (net_6lowpan_mode_extension == NET_6LOWPAN_WS) {
01184             ret_val = ws_bootstrap_init(interface_id, bootstrap_mode);
01185         } else {
01186             ret_val = arm_6lowpan_bootstarp_bootstrap_set(interface_id, bootstrap_mode, net_6lowpan_mode_extension);
01187         }
01188     }
01189 
01190     return ret_val;
01191 }
01192 
01193 int8_t arm_nwk_set_channel_list(int8_t interface_id, const channel_list_s *nwk_channel_list)
01194 {
01195     int8_t ret_val = -1;
01196     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
01197 
01198     if (!cur || !cur->mac_parameters) {
01199         return -1;
01200     }
01201 
01202     if (arm_channel_list_validation(nwk_channel_list)) {
01203         tr_debug("Given channel mask is empty!\n");
01204         return -2;
01205     }
01206 
01207     //CHECK Value
01208     if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
01209         return -4;
01210     }
01211 
01212     if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
01213         if (!cur->border_router_setup) {
01214             return -2;
01215         }
01216 
01217         const int channel_number = arm_net_channel_bit_mask_to_number(nwk_channel_list->channel_mask);
01218         if (channel_number < 0) {
01219             return -3;
01220         }
01221         cur->mac_parameters->mac_channel_list = *nwk_channel_list;
01222         cur->mac_parameters->mac_channel = channel_number;
01223         cur->border_router_setup->chanlist = &cur->mac_parameters->mac_channel_list;
01224         ret_val = 0;
01225     } else {
01226         // copy the channel information and store one internal pointer to it
01227         cur->mac_parameters->mac_channel_list = *nwk_channel_list;
01228         ret_val = 0;
01229     }
01230     return ret_val;
01231 }
01232 
01233 int8_t arm_nwk_6lowpan_link_scan_parameter_set(int8_t interface_id, uint8_t scan_time)
01234 {
01235     int8_t ret_val = -1;
01236     protocol_interface_info_entry_t *cur = 0;
01237 
01238     cur = protocol_stack_interface_info_get_by_id(interface_id);
01239     if (cur) {
01240         if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
01241             return -4;
01242         }
01243 
01244         if (cur->mac_parameters) {
01245             if (scan_time > 14) {
01246                 ret_val = -5;
01247             } else {
01248                 nwk_scan_params_t *scan_params = 0;
01249                 scan_params = &cur->mac_parameters->nwk_scan_params;
01250                 scan_params->scan_duration = scan_time;
01251                 ret_val = 0;
01252             }
01253         }
01254     }
01255     return ret_val;
01256 }
01257 
01258 int8_t arm_nwk_6lowpan_link_panid_filter_for_nwk_scan(int8_t interface_id, uint16_t pan_id_filter)
01259 {
01260     int8_t ret_val = -1;
01261     protocol_interface_info_entry_t *cur = 0;
01262     cur = protocol_stack_interface_info_get_by_id(interface_id);
01263     if (cur) {
01264         if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
01265             ret_val =  -2;
01266         } else if (cur->mac_parameters) {
01267             nwk_filter_params_s *filter = &(cur->mac_parameters->nwk_filter_params);
01268             filter->net_pan_id_filter = pan_id_filter;
01269             ret_val = 0;
01270         }
01271     }
01272     return ret_val;
01273 }
01274 
01275 int8_t arm_nwk_6lowpan_link_nwk_id_filter_for_nwk_scan(int8_t interface_id, const uint8_t *nwk_id_filter)
01276 {
01277     int8_t ret_val = -1;
01278     protocol_interface_info_entry_t *cur = 0;
01279     cur = protocol_stack_interface_info_get_by_id(interface_id);
01280     if (cur) {
01281 
01282         if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
01283             ret_val =  -2;
01284         } else if (cur->mac_parameters) {
01285             nwk_filter_params_s *filter = &(cur->mac_parameters->nwk_filter_params);
01286             ret_val = mac_helper_nwk_id_filter_set(nwk_id_filter, filter);
01287         }
01288     }
01289     return ret_val;
01290 }
01291 
01292 int8_t arm_nwk_6lowpan_link_protocol_id_filter_for_nwk_scan(int8_t interface_id, uint8_t protocol_ID)
01293 {
01294     int8_t ret_val = -1;
01295     protocol_interface_info_entry_t *cur = 0;
01296     cur = protocol_stack_interface_info_get_by_id(interface_id);
01297     if (cur) {
01298 
01299         if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
01300             ret_val =  -4;
01301         } else if (cur->mac_parameters) {
01302             nwk_filter_params_s *filter = &(cur->mac_parameters->nwk_filter_params);
01303             filter->beacon_protocol_id_filter = protocol_ID;
01304             ret_val = 0;
01305         }
01306     }
01307     return ret_val;
01308 }
01309 
01310 /* Don't have a loopback interface we can optimise for, but we do still need a route so we
01311  * can talk to ourself at all, in case our address isn't in an on-link prefix.
01312  */
01313 static void net_automatic_loopback_route_update(protocol_interface_info_entry_t *interface, const if_address_entry_t *addr, if_address_callback_t reason)
01314 {
01315     /* Don't care about link-local addresses - we know they're on-link */
01316     if (addr_is_ipv6_link_local(addr->address)) {
01317         return;
01318     }
01319 
01320     /* TODO: When/if we have a real loopback interface, these routes would use it instead of interface->id */
01321     switch (reason) {
01322         case ADDR_CALLBACK_DAD_COMPLETE:
01323             ipv6_route_add(addr->address, 128, interface->id, NULL, ROUTE_LOOPBACK, 0xFFFFFFFF, 0);
01324             break;
01325         case ADDR_CALLBACK_DELETED:
01326             ipv6_route_delete(addr->address, 128, interface->id, NULL, ROUTE_LOOPBACK);
01327             break;
01328         default:
01329             break;
01330     }
01331 }
01332 
01333 int8_t arm_nwk_6lowpan_beacon_join_priority_tx_callback_set(int8_t interface_id,
01334                                                             beacon_join_priority_tx_cb *beacon_join_priority_tx_cb_ptr)
01335 {
01336     return (mac_beacon_link_beacon_join_priority_tx_callback_set(interface_id, beacon_join_priority_tx_cb_ptr));
01337 }
01338 
01339 int8_t arm_nwk_6lowpan_beacon_compare_rx_callback_set(int8_t interface_id,
01340                                                       beacon_compare_rx_cb *beacon_compare_rx_cb_ptr)
01341 {
01342     return (mac_beacon_link_beacon_compare_rx_callback_set(interface_id, beacon_compare_rx_cb_ptr));
01343 }
01344 
01345 /**
01346   * \brief A function to initialize core elements of NanoStack library.
01347   *
01348   * \param core_idle is a function pointer to a function that is called whenever NanoStack is idle.
01349   * \return 0 on success.
01350   * \return -1 if a null pointer is given.
01351   */
01352 int8_t net_init_core(void)
01353 {
01354     /* Reset Protocol_stats */
01355     protocol_stats_init();
01356     protocol_core_init();
01357 #ifdef HAVE_RPL
01358     rpl_data_init();
01359     // XXX application should call these!
01360     rpl_of0_init();
01361     rpl_mrhof_init();
01362 #endif
01363     network_library_init();
01364     addr_notification_register(net_automatic_loopback_route_update);
01365     return 0;
01366 }
01367 
01368 static int8_t mac_data_poll_host_polling_state_change_check(protocol_interface_info_entry_t *cur)
01369 {
01370     int8_t ret_val = 0;
01371     if (cur->lowpan_info  & INTERFACE_NWK_ROUTER_DEVICE) {
01372         tr_warn("Host Control not accepted for Router");
01373         ret_val = -1;
01374     } else if (nwk_bootsrap_ready(cur) == 0) {
01375         tr_debug("Bootsrap Active");
01376         ret_val = -2;
01377     }
01378     return ret_val;
01379 }
01380 
01381 
01382 /**
01383   * \brief Set new Host state.
01384   *
01385   * \param mode new host state
01386   * \param poll_time poll time in seconds only handled when NET_HOST_SLOW_POLL_MODE is enabled
01387   *
01388   * Valid poll time for NET_HOST_SLOW_POLL_MODE is 0 < poll_time poll_time < 864001 (1 Day)
01389   *
01390   * \return 0, State update OK
01391   * \return -1, unknown state
01392   * \return -2, invalid time
01393   * \return -3 MLE handshake trig Fail
01394   *
01395   */
01396 int8_t arm_nwk_host_mode_set(int8_t interface_id, net_host_mode_t mode, uint32_t poll_time)
01397 {
01398     protocol_interface_info_entry_t *cur;
01399     cur = protocol_stack_interface_info_get_by_id(interface_id);
01400     if (!cur) {
01401         return -1;
01402     }
01403 
01404     if (mac_data_poll_host_polling_state_change_check(cur) != 0) {
01405         return -3;
01406     }
01407 
01408     net_host_mode_t old_mode;
01409 
01410     if (mac_data_poll_host_mode_get(cur, &old_mode) != 0) {
01411         return -1;
01412     }
01413 
01414     if (thread_info(cur)) {
01415         //save polltime for later use, polltime is zero for fast poll mode
01416         thread_info(cur)->sleepy_host_poll_time = 0;
01417         if (mode == NET_HOST_SLOW_POLL_MODE) {
01418             thread_info(cur)->sleepy_host_poll_time = poll_time;
01419         }
01420         if (old_mode == NET_HOST_RX_ON_IDLE && mode != old_mode
01421                 && thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_END_DEVICE) {
01422             tr_debug("End device changing to SED");
01423             thread_management_device_type_set(cur->id, THREAD_DEVICE_SED);
01424             return 0;
01425         }
01426     }
01427     return mac_data_poll_host_mode_set(cur, mode, poll_time);
01428 }
01429 
01430 /**
01431   * \brief Read Current Host State.
01432   *
01433   * \param mode pointer where host state will be saved
01434 
01435   * \return 0, State Read update OK
01436   * \return -1, Net Role is Router or stack is idle
01437   *
01438   */
01439 int8_t arm_nwk_host_mode_get(int8_t interface_id, net_host_mode_t *mode)
01440 {
01441     protocol_interface_info_entry_t *cur;
01442     cur = protocol_stack_interface_info_get_by_id(interface_id);
01443     if (!cur || !(cur->lowpan_info & INTERFACE_NWK_ACTIVE)) {
01444         return -1;
01445     }
01446 
01447     return mac_data_poll_host_mode_get(cur, mode);
01448 }
01449 
01450 
01451 int8_t net_nvm_data_clean(int8_t interface_id)
01452 {
01453     int8_t ret_val = -2; // Not ative
01454     protocol_interface_info_entry_t *cur = 0;
01455     cur = protocol_stack_interface_info_get_by_id(interface_id);
01456     if (cur) {
01457         if (cur->mac_parameters) {
01458             nwk_filter_params_s *filter = &(cur->mac_parameters->nwk_filter_params);
01459 
01460             if ((cur->lowpan_info & INTERFACE_NWK_ACTIVE) == 0) {
01461                 mac_helper_nwk_id_filter_set(0, filter);
01462                 mac_helper_panid_set(cur, 0xffff);
01463                 mac_helper_mac16_address_set(cur, 0xffff);
01464                 pana_reset_client_session();
01465                 ret_val = 0;
01466             } else {
01467                 ret_val = 0;
01468             }
01469         }
01470     }
01471 
01472     return ret_val;
01473 }
01474 
01475 
01476 static void trace_cmd_print(const char *fmt, ...)
01477 {
01478     va_list ap;
01479     va_start(ap, fmt);
01480     vtracef(TRACE_LEVEL_CMD, TRACE_GROUP, fmt, ap);
01481     va_end(ap);
01482 }
01483 void arm_print_routing_table(void)
01484 {
01485     arm_print_routing_table2(trace_cmd_print);
01486 }
01487 
01488 void arm_print_routing_table2(void (*print_fn)(const char *fmt, ...))
01489 {
01490     ipv6_destination_cache_print(print_fn);
01491     ipv6_route_table_print(print_fn);
01492 #ifdef HAVE_RPL
01493     rpl_control_print(print_fn);
01494 #endif
01495 }
01496 
01497 void arm_print_neigh_cache(void)
01498 {
01499     arm_print_neigh_cache2(trace_cmd_print);
01500 }
01501 
01502 void arm_print_neigh_cache2(void (*print_fn)(const char *fmt, ...))
01503 {
01504     nwk_interface_print_neigh_cache(print_fn);
01505 }
01506 
01507 void arm_print_protocols(void)
01508 {
01509     arm_print_protocols2(trace_cmd_print, ' ');
01510 }
01511 
01512 void arm_print_protocols2(void (*print_fn)(const char *fmt, ...), char sep)
01513 {
01514     socket_list_print(print_fn, sep);
01515 }
01516 
01517 void arm_ncache_flush(void)
01518 {
01519     nwk_interface_flush_neigh_cache();
01520 }
01521 
01522 int arm_nwk_sleepy_device_parent_buffer_size_set(int8_t interface_id, uint16_t big_packet_threshold, uint16_t small_packets_per_child_count, uint16_t big_packets_total_count)
01523 {
01524     protocol_interface_info_entry_t *cur;
01525 
01526     cur = protocol_stack_interface_info_get_by_id(interface_id);
01527     if (cur) {
01528         return lowpan_adaptation_indirect_queue_params_set(cur, big_packet_threshold,
01529                                                            big_packets_total_count, small_packets_per_child_count);
01530     }
01531     return -1;
01532 }
01533 
01534 int8_t arm_nwk_set_cca_threshold(int8_t interface_id, uint8_t cca_threshold)
01535 {
01536     protocol_interface_info_entry_t *cur;
01537     cur = protocol_stack_interface_info_get_by_id(interface_id);
01538     if (!cur || !cur->mac_api || (cca_threshold > 100)) {
01539         return -1;
01540     }
01541     mlme_set_t set_req;
01542     set_req.attr = macCCAThreshold;
01543     set_req.attr_index = 0;
01544     set_req.value_pointer = &cca_threshold;
01545     set_req.value_size = sizeof(cca_threshold);
01546     cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_req);
01547     return 0;
01548 }
01549 
01550 int8_t arm_nwk_set_tx_output_power(int8_t interface_id, uint8_t tx_power)
01551 {
01552     protocol_interface_info_entry_t *cur;
01553     cur = protocol_stack_interface_info_get_by_id(interface_id);
01554     if (!cur || !cur->mac_api || (tx_power > 100)) {
01555         return -1;
01556     }
01557     mlme_set_t set_req;
01558     set_req.attr = macTXPower;
01559     set_req.attr_index = 0;
01560     set_req.value_pointer = &tx_power;
01561     set_req.value_size = sizeof(tx_power);
01562     cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_req);
01563     return 0;
01564 }