takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ns_net.c Source File

ns_net.c

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