Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers protocol_6lowpan_bootstrap.c Source File

protocol_6lowpan_bootstrap.c

00001 /*
00002  * Copyright (c) 2015-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 /*
00019  * \file protocol_6lowpan_bootstrap.c
00020  *
00021  */
00022 #include "nsconfig.h"
00023 #include "string.h"
00024 #include "ns_types.h"
00025 #include "ns_trace.h"
00026 #include "eventOS_scheduler.h"
00027 #include "nsdynmemLIB.h"
00028 #include "randLIB.h"
00029 #include "NWK_INTERFACE/Include/protocol.h"
00030 #include "NWK_INTERFACE/Include/protocol_timer.h"
00031 #include "Common_Protocols/icmpv6.h"
00032 #include "Common_Protocols/icmpv6_radv.h"
00033 #include "Common_Protocols/udp.h"
00034 #include "6LoWPAN/Bootstraps/network_lib.h"
00035 #include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
00036 #include "6LoWPAN/Bootstraps/protocol_6lowpan_interface.h"
00037 #include "6LoWPAN/Bootstraps/protocol_6lowpan_bootstrap.h"
00038 #include "Service_Libs/blacklist/blacklist.h"
00039 #include "6LoWPAN/MAC/mac_helper.h"
00040 #include "mac_api.h"
00041 #include "net_pana_parameters_api.h"
00042 #ifdef HAVE_RPL
00043 #include "RPL/rpl_control.h"
00044 #endif
00045 #ifndef NO_MLE
00046 #include "MLE/mle.h"
00047 #include "MLE/mle_tlv.h"
00048 #endif
00049 #ifdef ECC
00050 #include "libX509_V3.h"
00051 #include "ecc.h"
00052 #endif
00053 
00054 #include "ccmLIB.h"
00055 #include "shalib.h"
00056 #include "net_nvm_api.h"
00057 #include "common_functions.h"
00058 #include "net_interface.h"
00059 #include "Security/TLS/tls_lib.h"
00060 #include "Security/Common/sec_lib.h"
00061 #include "Security/PANA/pana.h"
00062 #include "Security/PANA/pana_internal_api.h"
00063 #include "6LoWPAN/ND/nd_router_object.h"
00064 #include "BorderRouter/border_router.h"
00065 #include "6LoWPAN/Thread/thread_common.h"
00066 #include "Service_Libs/mle_service/mle_service_api.h"
00067 #include "Service_Libs/etx/etx.h"
00068 #include "6LoWPAN/MAC/beacon_handler.h"
00069 #include "mac_api.h"
00070 #include "6LoWPAN/MAC/mac_data_poll.h"
00071 #include "libNET/src/net_load_balance_internal.h"
00072 #include "6LoWPAN/lowpan_adaptation_interface.h"
00073 #include "6LoWPAN/NVM/nwk_nvm.h"
00074 #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
00075 
00076 
00077 /* Fixed-point randomisation limits for randlib_randomise_base() - RFC 3315
00078  * says RAND is uniformly distributed between -0.1 and +0.1
00079  */
00080 #define LOWPAN_RAND_LOW   0x7333 // 1 - 0.1; minimum for "1+RAND"
00081 #define LOWPAN_RAND_HIGH  0x8CCD // 1 + 0.1; maximum for "1+RAND"
00082 
00083 #define TRACE_GROUP_LOWPAN_BOOT "6Bo"
00084 #define TRACE_GROUP "6Bo"
00085 
00086 #ifdef HAVE_6LOWPAN_ND
00087 #ifdef HAVE_RPL
00088 static int protocol_6lowpan_router_multicast_synch(protocol_interface_info_entry_t *cur);
00089 static void protocol_6lowpan_bootstrap_rpl_callback(rpl_event_t event, void *handle);
00090 #else
00091 #define protocol_6lowpan_router_multicast_synch(cur) (-1)
00092 #endif
00093 
00094 static void protocol_6lowpan_mle_purge_neighbors(struct protocol_interface_info_entry *cur_interface, uint8_t entry_count, uint8_t force_priority);
00095 static uint8_t protocol_6lowpan_mle_order_last_entries(int8_t interface_id, mac_neighbor_table_list_t *mac_neigh_table, uint8_t entry_count);
00096 static uint8_t protocol_6lowpan_mle_data_allocate(void);
00097 static bool mle_accept_request_cb(int8_t interface_id, uint16_t msgId, bool usedAllRetries);
00098 static void lowpan_comm_status_indication_cb(int8_t if_id, const mlme_comm_status_t *status);
00099 
00100 static void protocol_6lowpan_priority_neighbor_remove(protocol_interface_info_entry_t *cur_interface, mac_neighbor_table_entry_t *cur);
00101 static void lowpan_neighbor_entry_remove_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data);
00102 static bool lowpan_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data);
00103 static bool protocol_6lowpan_router_challenge(protocol_interface_info_entry_t *cur_interface, const uint8_t *mac64);
00104 static bool protocol_6lowpan_host_challenge(protocol_interface_info_entry_t *cur, const uint8_t *mac64);
00105 static void protocol_6lowpan_address_reg_ready(protocol_interface_info_entry_t *cur_interface);
00106 static void coordinator_black_list(protocol_interface_info_entry_t *cur);
00107 
00108 static mle_6lowpan_data_t *mle_6lowpan_data;
00109 
00110 #define MAX_MC_DIS_COUNT 3
00111 
00112 static void lowpan_bootstrap_pan_control(protocol_interface_info_entry_t *cur, bool bootstrap_ready)
00113 {
00114     if (cur->mac_api) {
00115         mlme_start_t start_req;
00116         memset(&start_req, 0, sizeof(mlme_start_t));
00117         start_req.BeaconOrder = 15;
00118         start_req.SuperframeOrder = 15;
00119         start_req.PANCoordinator = bootstrap_ready;
00120         start_req.LogicalChannel = cur->mac_parameters->mac_channel;
00121         start_req.PANId = cur->mac_parameters->pan_id;
00122         cur->mac_api->mlme_req(cur->mac_api, MLME_START, &start_req);
00123         net_load_balance_internal_state_activate(cur, bootstrap_ready);
00124     }
00125 }
00126 
00127 static uint8_t lowpan_mode_get_by_interface_ptr(protocol_interface_info_entry_t *cur)
00128 {
00129     uint8_t mle_mode = 0;
00130 
00131     if (!(cur->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE)) {
00132         mle_mode |= MLE_RX_ON_IDLE;
00133     }
00134 
00135 
00136     if (cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) {
00137         mle_mode |= (MLE_FFD_DEV);
00138     }
00139 
00140     return mle_mode;
00141 }
00142 
00143 uint8_t *mle_general_write_timeout(uint8_t *ptr, protocol_interface_info_entry_t *cur)
00144 {
00145 
00146     uint32_t timeout_value = 0;
00147     uint8_t mode = lowpan_mode_get_by_interface_ptr(cur);
00148 
00149     if (!mle_6lowpan_data) {
00150         return ptr;
00151     }
00152 
00153     if (!(mode & MLE_RX_ON_IDLE)) {
00154         timeout_value = mac_data_poll_host_timeout(cur);
00155     }
00156     if (timeout_value == 0) {
00157         timeout_value = mle_6lowpan_data->host_lifetime;
00158     }
00159 
00160     return mle_tlv_write_timeout(ptr, timeout_value);
00161 
00162 }
00163 
00164 static void protocol_6lowpan_priority_neighbor_remove(protocol_interface_info_entry_t *cur_interface, mac_neighbor_table_entry_t *cur)
00165 {
00166     if (cur->link_role  != PRIORITY_PARENT_NEIGHBOUR ||
00167             !(cur_interface->lowpan_info & INTERFACE_NWK_ACTIVE) ||
00168             cur_interface->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
00169         return;
00170     }
00171 
00172     uint8_t mac64[8];
00173 
00174     if (cur_interface->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) {
00175         // Coordinating parent has been lost during bootstrap
00176         if (!cur_interface->global_address_available) {
00177             tr_debug("bootstrap coordinator down");
00178             bootsrap_next_state_kick(ER_BOOTSTRAP_CONNECTION_DOWN, cur_interface);
00179         }
00180     } else {
00181         //Call Priority parent loose
00182         if (cur->mac16  != 0xffff) {
00183             memcpy(mac64, ADDR_SHORT_ADR_SUFFIC, 6);
00184             common_write_16_bit(cur->mac16 , &mac64[6]);
00185         } else {
00186             memcpy(mac64, cur->mac64 , 8);
00187             mac64[0] ^= 2;
00188         }
00189 
00190         if (nd_parent_loose_indcate(mac64, cur_interface) != 0) {
00191             //ND Router synch lost
00192             tr_debug("ND Router Synch Loose");
00193             bootsrap_next_state_kick(ER_PARENT_SYNCH_LOST, cur_interface);
00194         }
00195     }
00196 }
00197 
00198 static bool protocol_6lowpan_challenge_callback(int8_t interface_id, uint16_t msgId, bool usedAllRetries)
00199 {
00200     protocol_interface_info_entry_t *cur_interface = protocol_stack_interface_info_get_by_id(interface_id);
00201     if (!cur_interface) {
00202         return false;
00203     }
00204 
00205     uint8_t mac64[8];
00206     uint8_t *ll64_ptr = mle_service_get_msg_destination_address_pointer(msgId);
00207 
00208     memcpy(mac64, ll64_ptr + 8, 8);
00209     mac64[0] ^= 2;
00210 
00211     mac_neighbor_table_entry_t *neig_info = mac_neighbor_table_address_discover(mac_neighbor_info(cur_interface), mac64, ADDR_802_15_4_LONG );
00212 
00213     if (!neig_info) {
00214         return false;//Why entry is removed before timeout??
00215     }
00216 
00217 
00218     if (!neig_info->nud_active ) {
00219         return false;
00220     }
00221 
00222 
00223     if (usedAllRetries) {
00224         //GET entry
00225         mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur_interface), neig_info);
00226         return false;
00227     }
00228 
00229     return true;
00230 }
00231 
00232 static bool protocol_6lowpan_host_challenge(protocol_interface_info_entry_t *cur, const uint8_t *mac64)
00233 {
00234     uint16_t bufId;
00235     mle_message_timeout_params_t timeout;
00236     uint8_t ll64[16];
00237 
00238 
00239     //Challenge
00240 
00241     uint8_t security_level = mle_service_security_level_get(cur->id);
00242     tr_debug("Link REQUEST");
00243     bufId = mle_service_msg_allocate(cur->id, 32, true, MLE_COMMAND_REQUEST);
00244     if (bufId == 0) {
00245         return false;
00246     }
00247 
00248     uint8_t *ptr = mle_service_get_data_pointer(bufId);
00249 
00250     ptr = mle_general_write_source_address(ptr, cur);
00251     ptr = mle_tlv_write_mode(ptr, lowpan_mode_get_by_interface_ptr(cur));
00252     if (security_level) {
00253         ptr = mle_general_write_link_layer_framecounter(ptr, cur);
00254     }
00255     if (cur->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE) {
00256         ptr = mle_general_write_timeout(ptr, cur);
00257     }
00258 
00259     memcpy(ll64, ADDR_LINK_LOCAL_PREFIX, 8);
00260     memcpy(&ll64[8], mac64, 8);
00261     ll64[8] ^= 2;
00262     if (mle_service_update_length_by_ptr(bufId, ptr) != 0) {
00263         tr_debug("Buffer overflow at message write");
00264     }
00265     timeout.retrans_max = 3;
00266     timeout.timeout_init = 2;
00267     timeout.timeout_max = 4;
00268     timeout.delay = MLE_NO_DELAY;
00269 
00270     //SET Destination address
00271     mle_service_set_msg_destination_address(bufId, ll64);
00272     //Set Callback
00273     mle_service_set_packet_callback(bufId, protocol_6lowpan_challenge_callback);
00274     mle_service_set_msg_timeout_parameters(bufId, &timeout);
00275 
00276     mle_service_send_message(bufId);
00277     return true;
00278 }
00279 
00280 static bool protocol_6lowpan_router_challenge(protocol_interface_info_entry_t *cur, const uint8_t *mac64)
00281 {
00282 
00283     uint16_t bufId;
00284     mle_message_timeout_params_t timeout;
00285     uint8_t ll64[16];
00286 
00287 
00288     //Challenge
00289 
00290     uint8_t security_level = mle_service_security_level_get(cur->id);
00291     tr_debug("Link REQUEST");
00292     bufId = mle_service_msg_allocate(cur->id, 32, true, MLE_COMMAND_REQUEST);
00293     if (bufId == 0) {
00294         return false;
00295     }
00296 
00297     uint8_t *ptr = mle_service_get_data_pointer(bufId);
00298 
00299     ptr = mle_general_write_source_address(ptr, cur);
00300     ptr = mle_tlv_write_mode(ptr, lowpan_mode_get_by_interface_ptr(cur));
00301     if (security_level) {
00302         ptr = mle_general_write_link_layer_framecounter(ptr, cur);
00303     }
00304 
00305     memcpy(ll64, ADDR_LINK_LOCAL_PREFIX, 8);
00306     memcpy(&ll64[8], mac64, 8);
00307     ll64[8] ^= 2;
00308     if (mle_service_update_length_by_ptr(bufId, ptr) != 0) {
00309         tr_debug("Buffer overflow at message write");
00310     }
00311     timeout.retrans_max = 2;
00312     timeout.timeout_init = 2;
00313     timeout.timeout_max = 4;
00314     timeout.delay = MLE_NO_DELAY;
00315 
00316     //SET Destination address
00317     mle_service_set_msg_destination_address(bufId, ll64);
00318     mle_service_set_msg_timeout_parameters(bufId, &timeout);
00319 
00320     mle_service_send_message(bufId);
00321     return true;
00322 }
00323 
00324 
00325 static uint8_t mle_advert_neigh_cnt(protocol_interface_info_entry_t *cur_interface, bool short_adr)
00326 {
00327 
00328     uint8_t advert_neigh_cnt;
00329     uint8_t neighb_max;
00330 
00331     uint8_t mle_neigh_cnt = mle_class_active_neigh_counter(cur_interface);
00332 
00333     if (short_adr == true) {
00334         neighb_max = 16;
00335     } else {
00336         neighb_max = 5;
00337     }
00338 
00339     if (mle_neigh_cnt > neighb_max) {
00340         advert_neigh_cnt = neighb_max;
00341     } else {
00342         advert_neigh_cnt = mle_neigh_cnt;
00343     }
00344 
00345     return (advert_neigh_cnt);
00346 }
00347 
00348 static uint8_t mle_link_quality_tlv_parse(uint8_t *mac64, uint16_t short_address, uint8_t *ptr, uint16_t data_length, uint8_t *iop_flags_ptr, uint8_t *link_idr_ptr)
00349 {
00350     uint8_t entry_size;
00351 
00352     if (data_length) {
00353         entry_size = (*ptr++ & 0x0f) + 3;
00354         data_length--;
00355 
00356         // Supports 2 and 8 bytes long MAC addresses
00357         if ((entry_size == 4) || (entry_size == 10)) {
00358 
00359             uint8_t own_addr_match = false;
00360 
00361             // Searches own address from link quality TLV
00362             while (data_length >= entry_size) {
00363 
00364                 if (entry_size == 4) {
00365                     if (common_read_16_bit(ptr + 2) == short_address) {
00366                         own_addr_match = true;
00367                     }
00368                 } else {
00369                     if (memcmp(ptr + 2, mac64, 8) == 0) {
00370                         own_addr_match = true;
00371                     }
00372                 }
00373 
00374                 // If own address is found returns success
00375                 if (own_addr_match) {
00376                     if (iop_flags_ptr) {
00377                         *iop_flags_ptr = ptr[0];
00378                     }
00379                     if (link_idr_ptr) {
00380                         *link_idr_ptr = ptr[1];
00381                     }
00382                     return 1;
00383                 }
00384 
00385                 ptr += entry_size;
00386                 data_length -= entry_size;
00387             }
00388         }
00389     }
00390     return 0;
00391 }
00392 
00393 static bool neighbor_list_short_address_available(mac_neighbor_table_t *table_class)
00394 {
00395     ns_list_foreach(mac_neighbor_table_entry_t, cur_entry, &table_class->neighbour_list ) {
00396         if (cur_entry->connected_device && cur_entry->mac16 == 0xffff) {
00397             return false;
00398         }
00399     }
00400     return true;
00401 }
00402 
00403 
00404 static uint8_t *mle_table_set_neighbours(protocol_interface_info_entry_t *cur, uint8_t *ptr)
00405 {
00406     uint8_t *len_ptr = 0;
00407     uint8_t neigh_count = 0;
00408     uint8_t neigh_count_max = 0;
00409     uint8_t *link_flags_ptr;
00410     mac_neighbor_table_entry_t *first_entry_ptr = NULL;
00411 
00412     mac_neighbor_table_list_t *neigh_list = &cur->mac_parameters->mac_neighbor_table->neighbour_list;
00413 
00414     *ptr++ = MLE_TYPE_LINK_QUALITY;
00415     len_ptr = ptr++;
00416     *len_ptr = 1;
00417 
00418     link_flags_ptr = ptr++;
00419     //*link_flags_ptr = 0x81;
00420     bool use_short_address_compression = neighbor_list_short_address_available(mac_neighbor_info(cur));
00421     if (use_short_address_compression) {
00422         //complete, 2 bytes long link-layer address
00423         *link_flags_ptr = 0x81;
00424     } else {
00425         //complete, 8 bytes long link-layer address
00426         *link_flags_ptr = 0x87;
00427 
00428     }
00429     neigh_count_max = mle_advert_neigh_cnt(cur, use_short_address_compression);
00430 
00431     bool clean_entries = false;
00432     ns_list_foreach(mac_neighbor_table_entry_t, cur_entry, neigh_list) {
00433 
00434         if ((cur_entry->connected_device) && (cur_entry->advertisment == false)) {
00435 
00436             // If looping list, stops adding entries when at first sent entry again
00437             if (first_entry_ptr == cur_entry) {
00438                 break;
00439             } else if (first_entry_ptr == NULL) {
00440                 first_entry_ptr = cur_entry;
00441             }
00442 
00443             // Limits the number of entries that are sent
00444             if (++neigh_count > neigh_count_max) {
00445                 *link_flags_ptr &= 0x7f;
00446                 break;
00447             }
00448 
00449             if (cur_entry->link_role == PRIORITY_PARENT_NEIGHBOUR) {
00450                 *ptr++ = MLE_NEIGHBOR_PRIORITY_LINK | MLE_NEIGHBOR_INCOMING_LINK | MLE_NEIGHBOR_OUTGOING_LINK;
00451             } else {
00452                 *ptr++ = MLE_NEIGHBOR_INCOMING_LINK | MLE_NEIGHBOR_OUTGOING_LINK;
00453             }
00454 
00455             *ptr++ = etx_local_incoming_idr_read(cur->id, cur_entry->index) >> 3;
00456 
00457             if (use_short_address_compression) {
00458                 ptr = common_write_16_bit(cur_entry->mac16, ptr);
00459                 *len_ptr += 4;
00460             } else {
00461                 memcpy(ptr, cur_entry->mac64, 8);
00462                 ptr += 8;
00463                 *len_ptr += 10;
00464             }
00465 
00466             // If end of the neighbor list, Mark a clean advertisment from the list
00467             if (cur_entry->link.next == 0) {
00468                 clean_entries = true;
00469             }
00470             cur_entry->advertisment = true;
00471         }
00472     }
00473 
00474     if (clean_entries) {
00475         ns_list_foreach(mac_neighbor_table_entry_t, temp, neigh_list) {
00476             // Marks entries not sent
00477             temp->advertisment = false;
00478         }
00479     }
00480 
00481     return ptr;
00482 }
00483 
00484 #ifndef NO_MLE
00485 static int protocol_6lowpan_mle_neigh_advertise(protocol_interface_info_entry_t *cur)
00486 {
00487     /* How was this 40 calculated? Seems to be more than enough, at least.
00488      * MODE = 2+1, SRC_ADDR = 2+2, LINK = 2+1+4*neighbours, ROUTE = 2+MLE_ROUTE_MIN_OPTION_LEN+routers
00489      * Total = 10 + neighbours * 4
00490      */
00491     uint16_t neig_cache_size = 40 + 7;
00492     uint8_t short_temp[2] = {0xff, 0xff};
00493     uint8_t *ptr;
00494     mle_message_timeout_params_t timeout;
00495 
00496     if (!cur) {
00497         return 0;
00498     }
00499 
00500     if (mac_neighbor_table_address_discover(mac_neighbor_info(cur), short_temp, ADDR_802_15_4_SHORT )) {
00501         neig_cache_size += mle_advert_neigh_cnt(cur, false) * 10;
00502     } else {
00503         neig_cache_size += mle_advert_neigh_cnt(cur, true) << 2;
00504     }
00505 
00506     uint16_t bufId = mle_service_msg_allocate(cur->id, neig_cache_size, false, MLE_COMMAND_ADVERTISEMENT);
00507 
00508     if (bufId == 0) {
00509         return -1;
00510     }
00511 
00512     timeout.retrans_max = 0;
00513     timeout.timeout_init = 0;
00514     timeout.timeout_max = 0;
00515     timeout.delay = MLE_NO_DELAY;
00516 
00517     tr_debug("Send MLE Advertisement");
00518     mle_service_set_msg_destination_address(bufId, ADDR_LINK_LOCAL_ALL_ROUTERS);
00519     mle_service_set_msg_timeout_parameters(bufId, &timeout);
00520 
00521     ptr = mle_service_get_data_pointer(bufId);
00522     ptr = mle_general_write_source_address(ptr, cur);
00523     ptr = mle_tlv_write_mode(ptr, lowpan_mode_get_by_interface_ptr(cur));
00524     ptr = mle_table_set_neighbours(cur, ptr);
00525 
00526     if (mle_service_update_length_by_ptr(bufId, ptr) != 0) {
00527         tr_debug("Buffer overflow at message write");
00528     }
00529 
00530     return mle_service_send_message(bufId);
00531 }
00532 #endif
00533 
00534 static int mle_validate_6lowpan_link_request_message(uint8_t *ptr, uint16_t data_len, mle_tlv_info_t *tlv_info)
00535 {
00536     /**
00537      * MLE Request need to include always challenge
00538      * - MLE_TYPE_CHALLENGE
00539      */
00540     if (mle_tlv_option_discover(ptr, data_len, MLE_TYPE_CHALLENGE, tlv_info) < 4) {
00541         // TLV not found or length is smaller than 4
00542         return -1;
00543     }
00544     return 0;
00545 }
00546 
00547 static void mle_neigh_time_and_mode_update(mac_neighbor_table_entry_t *entry_temp, mle_message_t *mle_msg)
00548 {
00549     uint8_t *tlv_ptr = mle_msg->data_ptr;
00550     uint16_t tlv_length = mle_msg->data_length;
00551 
00552     mle_tlv_info_t mle_tlv_info;
00553     uint32_t timeout_tlv;
00554 
00555     if (!mle_6lowpan_data) {
00556         return;
00557     }
00558 
00559     protocol_interface_info_entry_t *cur = mle_msg->interface_ptr;
00560 
00561     if (mle_tlv_option_discover(tlv_ptr, tlv_length, MLE_TYPE_MODE, &mle_tlv_info) > 0) {
00562         uint8_t *t_ptr = mle_tlv_info.dataPtr;
00563         mle_mode_parse_to_mac_entry(entry_temp, *t_ptr);
00564     }
00565 
00566     if (mle_tlv_option_discover(tlv_ptr, tlv_length, MLE_TYPE_TIMEOUT, &mle_tlv_info) > 0) {
00567         timeout_tlv = common_read_32_bit(mle_tlv_info.dataPtr);
00568     } else {
00569         if (entry_temp->ffd_device ) {
00570             timeout_tlv = mle_6lowpan_data->router_lifetime;
00571         } else {
00572             timeout_tlv = mle_6lowpan_data->host_lifetime;
00573         }
00574     }
00575     mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, timeout_tlv);
00576 }
00577 
00578 static void mle_neigh_entry_update_by_mle_tlv_list(int8_t interface_id, mac_neighbor_table_entry_t *entry_temp, uint8_t *tlv_ptr, uint16_t tlv_length, uint8_t *mac64, uint16_t short_address)
00579 {
00580     mle_tlv_info_t mle_tlv_info;
00581 
00582     if (tlv_length) {
00583         if (mle_tlv_option_discover(tlv_ptr, tlv_length, MLE_TYPE_SRC_ADDRESS, &mle_tlv_info) > 0) {
00584             entry_temp->mac16  = common_read_16_bit(mle_tlv_info.dataPtr);
00585         }
00586 
00587         if (mle_tlv_option_discover(tlv_ptr, tlv_length, MLE_TYPE_LINK_QUALITY, &mle_tlv_info) > 0) {
00588             uint8_t link_idr;
00589             uint8_t iop_flags;
00590             if (mle_link_quality_tlv_parse(mac64, short_address, mle_tlv_info.dataPtr, mle_tlv_info.tlvLen, &iop_flags, &link_idr)) {
00591                 etx_remote_incoming_idr_update(interface_id, link_idr, entry_temp->index );
00592 
00593                 if ((iop_flags & MLE_NEIGHBOR_PRIORITY_LINK) == MLE_NEIGHBOR_PRIORITY_LINK) {
00594                     entry_temp->link_role  = CHILD_NEIGHBOUR;
00595                 } else if (entry_temp->link_role  == CHILD_NEIGHBOUR) {
00596                     entry_temp->link_role  = NORMAL_NEIGHBOUR;
00597                 }
00598             }
00599         }
00600     }
00601 
00602 }
00603 
00604 //Generate link request
00605 static uint16_t mle_router_synch(protocol_interface_info_entry_t *cur, const uint8_t *destAddress, uint8_t delay, uint8_t incoming_idr, bool retrans, bool register_short)
00606 {
00607     mle_message_timeout_params_t timeout;
00608     uint16_t bufId = mle_service_msg_allocate(cur->id, 64, true, MLE_COMMAND_REQUEST);
00609     if (bufId == 0) {
00610         return 0;
00611     }
00612 
00613     uint8_t security_level = mle_service_security_level_get(cur->id);
00614 
00615     uint8_t *ptr = mle_service_get_data_pointer(bufId);
00616     if (register_short) {
00617         ptr = mle_tlv_write_source_address(ptr, cur->lowpan_desired_short_address);
00618     } else {
00619         ptr = mle_general_write_source_address(ptr, cur);
00620     }
00621     ptr = mle_tlv_write_mode(ptr, lowpan_mode_get_by_interface_ptr(cur));
00622     if (security_level) {
00623         ptr = mle_general_write_link_layer_framecounter(ptr, cur);
00624     }
00625     if (cur->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE) {
00626         ptr = mle_general_write_timeout(ptr, cur);
00627     }
00628 
00629     if (destAddress && incoming_idr != 0) {
00630         uint8_t mac64[8];
00631         memcpy(mac64, &destAddress[8], 8);
00632         mac64[0] ^= 2;
00633         ptr = mle_tlv_write_link_quality(ptr, incoming_idr, mac64, 0, false);
00634     }
00635 
00636     if (destAddress) {
00637         mle_service_set_msg_destination_address(bufId, destAddress);
00638     } else {
00639         mle_service_set_msg_destination_address(bufId, ADDR_LINK_LOCAL_ALL_ROUTERS);
00640     }
00641 
00642     if (retrans) {
00643         if (destAddress) {
00644             timeout.retrans_max = 3;
00645             timeout.timeout_init = 2;
00646             timeout.timeout_max = 4;
00647         } else {
00648             timeout.retrans_max = 2;
00649             timeout.timeout_init = 4;
00650             timeout.timeout_max = 4;
00651         }
00652     } else {
00653         timeout.retrans_max = 1;
00654         timeout.timeout_init = 2;
00655         timeout.timeout_max = 4;
00656     }
00657 
00658     timeout.delay = delay;
00659 
00660     if (mle_service_update_length_by_ptr(bufId, ptr) != 0) {
00661         tr_debug("Buffer overflow at message write");
00662     }
00663 
00664     mle_service_set_msg_timeout_parameters(bufId, &timeout);
00665     mle_service_send_message(bufId);
00666     return bufId;
00667 }
00668 
00669 static int mle_router_accept_request_build(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint8_t *challenge, uint8_t chalLen, uint8_t type, uint8_t incoming_idr, uint8_t priority_flag)
00670 {
00671     uint16_t bufId;
00672     uint8_t mac64[8];
00673     mle_message_timeout_params_t timeout;
00674 
00675     uint8_t security_level = mle_service_security_level_get(cur->id);
00676 
00677 
00678 
00679     if (type == MLE_COMMAND_ACCEPT) {
00680         bufId =  mle_service_msg_allocate(cur->id, 64, false, type);
00681         timeout.retrans_max = 0;
00682         timeout.timeout_init = 0;
00683         timeout.timeout_max = 0;
00684     } else {
00685         bufId =  mle_service_msg_allocate(cur->id, 64, true, type);
00686         timeout.retrans_max = 2;
00687         timeout.timeout_init = 2;
00688         timeout.timeout_max = 4;
00689     }
00690 
00691     if (bufId == 0) {
00692         return -1;
00693     }
00694 
00695     if (addr_is_ipv6_multicast(mle_msg->packet_dst_address)) {
00696         timeout.delay = MLE_STANDARD_RESPONSE_DELAY;
00697     } else {
00698         timeout.delay = MLE_NO_DELAY;
00699     }
00700 
00701     tr_debug("MLE Router Link Request response");
00702 
00703     mle_service_set_msg_destination_address(bufId, mle_msg->packet_src_address);
00704 
00705     uint8_t *ptr = mle_service_get_data_pointer(bufId);
00706     ptr = mle_tlv_write_mode(ptr, lowpan_mode_get_by_interface_ptr(cur));
00707 
00708     if (security_level) {
00709         ptr = mle_general_write_link_layer_framecounter(ptr, cur);
00710     }
00711 
00712     if (challenge && chalLen) {
00713 
00714         ptr = mle_tlv_write_response(ptr, challenge, chalLen);
00715     }
00716 
00717     memcpy(mac64, &mle_msg->packet_src_address[8], 8);
00718     mac64[0] ^= 2;
00719     ptr = mle_tlv_write_link_quality(ptr, incoming_idr, mac64, 0, priority_flag);
00720 
00721     ptr = mle_general_write_source_address(ptr, cur);
00722     if (mle_service_update_length_by_ptr(bufId, ptr) != 0) {
00723         tr_debug("Buffer overflow at message write");
00724     }
00725     mle_service_set_msg_timeout_parameters(bufId, &timeout);
00726 
00727     if (type == MLE_COMMAND_ACCEPT) {
00728         mle_service_set_msg_token_bucket_priority(bufId);
00729     } else {
00730         mle_service_set_packet_callback(bufId, mle_accept_request_cb);
00731     }
00732 
00733     mle_service_send_message(bufId);
00734     return 0;
00735 }
00736 
00737 static void protocol_6lowpan_link_reject_handler(protocol_interface_info_entry_t *cur, uint8_t *ll64)
00738 {
00739     mac_neighbor_table_entry_t *mac_entry = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), ll64, false, NULL);
00740     tr_debug("MLE link reject");
00741     if (mac_entry) {
00742         mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), mac_entry);
00743     }
00744 }
00745 
00746 static bool mle_child_update_cb(int8_t interface_id, uint16_t msgId, bool usedAllRetries)
00747 {
00748     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00749     if (!cur) {
00750         return false;
00751     }
00752 
00753     if (mle_service_check_msg_response(msgId)) {
00754         return false;
00755     }
00756 
00757     if (usedAllRetries) {
00758         tr_debug("Link Update fail-->Reset bootstrap");
00759         mac_data_poll_protocol_poll_mode_decrement(cur);
00760         bootsrap_next_state_kick(ER_BOOTSTRAP_CONNECTION_DOWN, cur);
00761 
00762         return false;
00763     }
00764     mac_data_poll_protocol_poll_mode_decrement(cur);
00765     return true;
00766 }
00767 
00768 int protocol_6lowpan_child_update(protocol_interface_info_entry_t *cur)
00769 {
00770     uint16_t bufId;
00771     uint8_t cordAddress[16];
00772     if (protocol_6lowpan_interface_get_link_local_cordinator_address(cur, cordAddress) != 0) {
00773         return -1;
00774     }
00775 
00776     bufId = mle_router_synch(cur, cordAddress, MLE_NO_DELAY, 0, true, false);
00777     if (bufId == 0) {
00778         return -1;
00779     }
00780 
00781     return mle_service_set_packet_callback(bufId, mle_child_update_cb);
00782 
00783 }
00784 
00785 static bool mle_parent_link_req_cb(int8_t interface_id, uint16_t msgId, bool usedAllRetries)
00786 {
00787     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00788     if (!cur) {
00789         return false;
00790     }
00791 
00792     if (mle_service_check_msg_response(msgId)) {
00793         if (cur->nwk_bootstrap_state == ER_MLE_LINK_REQ) {
00794             //Enter ND scan
00795             bootsrap_next_state_kick(ER_SCAN, cur);
00796             pan_coordinator_blacklist_free(&cur->pan_cordinator_black_list);
00797         }
00798 #ifdef HAVE_RPL
00799         else if (cur->nwk_bootstrap_state == ER_ROUTER_SYNCH) {
00800             //Trig RPL multicast dis
00801             cur->nwk_bootstrap_state = ER_RPL_MC;
00802             cur->bootsrap_state_machine_cnt = 55;
00803         }
00804 #endif
00805         else if (cur->nwk_bootstrap_state == ER_MLE_LINK_ADDRESS_SYNCH) {
00806             mac_data_poll_protocol_poll_mode_disable(cur);
00807             bootsrap_next_state_kick(ER_BOOTSRAP_DONE, cur);
00808 
00809         } else if (cur->nwk_bootstrap_state == ER_MLE_LINK_SHORT_SYNCH) {
00810             tr_debug("MAC16 address synch ready");
00811             //SET Here 16-bit
00812             //SET MAC16 Address & LL16
00813             mac_helper_mac16_address_set(cur, cur->lowpan_desired_short_address);
00814             protocol_6lowpan_set_ll16(cur, cur->lowpan_desired_short_address);
00815             protocol_6lowpan_address_reg_ready(cur);
00816         }
00817         return false;
00818     }
00819 
00820     if (usedAllRetries) {
00821         switch (cur->nwk_bootstrap_state) {
00822             case ER_MLE_LINK_REQ:
00823             case ER_MLE_LINK_ADDRESS_SYNCH:
00824             case ER_MLE_LINK_SHORT_SYNCH:
00825                 if (cur->nwk_bootstrap_state == ER_MLE_LINK_REQ) {
00826                     coordinator_black_list(cur);
00827                 }
00828                 tr_debug("Link synch fail %u", cur->nwk_bootstrap_state);
00829                 bootsrap_next_state_kick(ER_BOOTSTRAP_CONNECTION_DOWN, cur);
00830                 break;
00831 #ifdef HAVE_RPL
00832             case ER_ROUTER_SYNCH:
00833                 bootsrap_next_state_kick(ER_RPL_MC, cur);
00834                 break;
00835 #endif // HAVE_RPL
00836             default:
00837                 break;
00838         }
00839         return false;
00840     }
00841     return true;
00842 }
00843 
00844 static bool mle_accept_request_cb(int8_t interface_id, uint16_t msgId, bool usedAllRetries)
00845 {
00846     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00847     if (!cur) {
00848         return false;
00849     }
00850 
00851     if (mle_service_check_msg_response(msgId)) {
00852         return false;
00853     }
00854 
00855     if (usedAllRetries) {
00856         //If message has been sent by MLE service sends MLE reject to clear link
00857         if (mle_service_check_msg_sent(msgId)) {
00858             uint8_t *address_ptr = mle_service_get_msg_destination_address_pointer(msgId);
00859             tr_debug("No accept for Accept/Request");
00860             mle_service_reject_message_build(cur->id, address_ptr, false);
00861         }
00862         return false;
00863     }
00864     return true;
00865 }
00866 
00867 int protocol_6lowpan_parent_link_req(protocol_interface_info_entry_t *cur)
00868 {
00869     uint16_t bufId;
00870     uint8_t cordAddress[16];
00871     if (protocol_6lowpan_interface_get_link_local_cordinator_address(cur, cordAddress) != 0) {
00872         return -1;
00873     }
00874 
00875     bufId = mle_router_synch(cur, cordAddress, MLE_NO_DELAY, 0, true, false);
00876     if (bufId == 0) {
00877         tr_debug("No Buf");
00878         return -1;
00879     }
00880     cur->nwk_bootstrap_state = ER_MLE_LINK_REQ;
00881 
00882     return mle_service_set_packet_callback(bufId, mle_parent_link_req_cb);
00883 
00884 }
00885 #ifdef HAVE_RPL
00886 static int protocol_6lowpan_router_multicast_synch(protocol_interface_info_entry_t *cur)
00887 {
00888     uint16_t bufId;
00889 
00890     bufId = mle_router_synch(cur, NULL, MLE_NO_DELAY, 0, true, false);
00891 
00892     if (bufId == 0) {
00893         return -1;
00894     }
00895     cur->nwk_bootstrap_state = ER_ROUTER_SYNCH;
00896 
00897     return mle_service_set_packet_callback(bufId, mle_parent_link_req_cb);
00898 }
00899 #endif
00900 
00901 static int protocol_6lowpan_parent_address_synch(protocol_interface_info_entry_t *cur, bool register_short)
00902 {
00903     uint16_t bufId;
00904 
00905     uint8_t cordAddress[16];
00906     if (protocol_6lowpan_interface_get_link_local_cordinator_address(cur, cordAddress) != 0) {
00907         return -1;
00908     }
00909 
00910     bufId = mle_router_synch(cur, cordAddress, MLE_NO_DELAY, 0, true, register_short);
00911     if (bufId == 0) {
00912         return -1;
00913     }
00914     if (register_short) {
00915         cur->nwk_bootstrap_state = ER_MLE_LINK_SHORT_SYNCH;
00916 
00917     } else {
00918         cur->nwk_bootstrap_state = ER_MLE_LINK_ADDRESS_SYNCH;
00919     }
00920 
00921     return mle_service_set_packet_callback(bufId, mle_parent_link_req_cb);
00922 }
00923 
00924 static bool mle_new_link_req_cb(int8_t interface_id, uint16_t msgId, bool usedAllRetries)
00925 {
00926     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00927     if (!cur) {
00928         return false;
00929     }
00930 
00931     uint8_t *address_ptr = mle_service_get_msg_destination_address_pointer(msgId);
00932 
00933     if (mle_service_check_msg_response(msgId)) {
00934         if (address_ptr && !addr_is_ipv6_multicast(address_ptr)) {
00935             // Remove from blacklist
00936             blacklist_update(address_ptr, true);
00937         }
00938         return false;
00939     }
00940 
00941     if (usedAllRetries) {
00942         if (address_ptr && !addr_is_ipv6_multicast(address_ptr)) {
00943             tr_warn("Sync fail to new router");
00944             // Add to blacklist or update current entry
00945             blacklist_update(address_ptr, false);
00946         }
00947         return false;
00948     }
00949     return true;
00950 }
00951 
00952 int protocol_6lowpan_router_synch_to_new_router(protocol_interface_info_entry_t *cur, uint8_t *ll64, uint8_t incoming_idr, bool retrans)
00953 {
00954     uint16_t bufId;
00955 
00956     bufId = mle_router_synch(cur, ll64, MLE_STANDARD_RESPONSE_DELAY, incoming_idr, retrans, false);
00957     if (bufId == 0) {
00958         return -1;
00959     }
00960 
00961     return mle_service_set_packet_callback(bufId, mle_new_link_req_cb);
00962 }
00963 
00964 
00965 static uint8_t mle_calculate_idr(int8_t interface_id, mle_message_t *mle_msg, mac_neighbor_table_entry_t *entry_temp)
00966 {
00967     if (!entry_temp) {
00968         return etx_lqi_dbm_update(-2, mle_msg->lqi, mle_msg->dbm, 0) >> 3;
00969     }
00970     return etx_lqi_dbm_update(interface_id, mle_msg->lqi, mle_msg->dbm, entry_temp->index ) >> 3;
00971 
00972 }
00973 
00974 static bool mle_6lowpan_neighbor_limit_check(mle_message_t *mle_msg, uint8_t only_max_limit_chk)
00975 {
00976     uint16_t mle_neigh_cnt;
00977     bool link_quality = false;
00978 
00979     if (!mle_6lowpan_data || mle_6lowpan_data->nbr_of_neigh_max == 0) {
00980         return true;
00981     }
00982 
00983     mle_neigh_cnt = mle_class_active_neigh_counter(mle_msg->interface_ptr);
00984 
00985     // Neighbor max limit
00986     if (mle_neigh_cnt >= mle_6lowpan_data->nbr_of_neigh_max) {
00987         tr_debug("Number of neighbor max limit");
00988         return false;
00989     }
00990 
00991     if (only_max_limit_chk) {
00992         return true;
00993     }
00994 
00995     if (mle_msg->message_type == MLE_COMMAND_REQUEST) {
00996         mle_tlv_info_t mle_tlv_info;
00997         if (mle_tlv_option_discover(mle_msg->data_ptr, mle_msg->data_length, MLE_TYPE_LINK_QUALITY, &mle_tlv_info) > 0) {
00998             link_quality = true;
00999         }
01000     }
01001 
01002     // Lower threshold reached, start to limit answering to multicast messages
01003     if (mle_neigh_cnt >= mle_6lowpan_data->nbr_of_neigh_lower_threshold) {
01004         // If multicast link request or link request was triggered from advertisement
01005         if (addr_is_ipv6_multicast(mle_msg->packet_dst_address) || link_quality == true) {
01006 
01007             // Upper threshold reached, no responses to multicasts anymore
01008             if (mle_neigh_cnt >= mle_6lowpan_data->nbr_of_neigh_upper_threshold) {
01009                 return false;
01010             }
01011 
01012             uint16_t ignore_prob = randLIB_get_random_in_range(1,
01013                                                                mle_6lowpan_data->nbr_of_neigh_upper_threshold - mle_6lowpan_data->nbr_of_neigh_lower_threshold);
01014 
01015             if (ignore_prob < (mle_neigh_cnt - mle_6lowpan_data->nbr_of_neigh_lower_threshold)) {
01016                 return false;
01017             }
01018         }
01019     }
01020 
01021     return true;
01022 }
01023 
01024 void mle_6lowpan_message_handler(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers)
01025 {
01026     uint8_t *t_ptr;
01027     uint8_t response_type;
01028     uint8_t mode = 0x0a;
01029     mle_tlv_info_t mle_tlv_info;
01030     mle_tlv_info_t mle_challenge;
01031     mac_neighbor_table_entry_t *entry_temp;
01032     uint8_t incoming_idr;
01033     uint16_t responseId, own_mac16;
01034     protocol_interface_info_entry_t *cur = mle_msg->interface_ptr;
01035 
01036 
01037     own_mac16 = mac_helper_mac16_address_get(cur);
01038 
01039     switch (mle_msg->message_type) {
01040         case MLE_COMMAND_REQUEST:
01041             tr_debug("Link REQ");
01042             if (!cur->global_address_available) {
01043                 return;
01044             } else if (mle_validate_6lowpan_link_request_message(mle_msg->data_ptr, mle_msg->data_length, &mle_challenge) != 0) {
01045                 return;
01046             }
01047 
01048             entry_temp = NULL;
01049             //If link request frame counter is invalid do not update neighbor entry and use three way handshake
01050             if (security_headers->invalid_frame_counter) {
01051                 //Limit rate for triggering link requests
01052                 if (!mle_6lowpan_data->link_req_token_bucket) {
01053                     return;
01054                 }
01055                 mle_6lowpan_data->link_req_token_bucket--;
01056             } else {
01057                 //Update only old information based on link request
01058                 entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
01059                 if (entry_temp) {
01060                     mle_neigh_time_and_mode_update(entry_temp, mle_msg);
01061                     mle_neigh_entry_update_by_mle_tlv_list(interface_id, entry_temp, mle_msg->data_ptr, mle_msg->data_length, cur->mac, own_mac16);
01062                     mle_neigh_entry_frame_counter_update(entry_temp, mle_msg->data_ptr, mle_msg->data_length, cur, security_headers->KeyIndex);
01063                 } else {
01064                     if (!mle_6lowpan_neighbor_limit_check(mle_msg, false)) {
01065                         return;
01066                     }
01067                 }
01068             }
01069 
01070             incoming_idr = mle_calculate_idr(interface_id, mle_msg, entry_temp);
01071 
01072             if (entry_temp && entry_temp->connected_device ) {
01073                 response_type = MLE_COMMAND_ACCEPT;
01074             } else {
01075                 response_type = MLE_COMMAND_ACCEPT_AND_REQUEST;
01076             }
01077             mle_router_accept_request_build(cur, mle_msg, mle_challenge.dataPtr, mle_challenge.tlvLen, response_type, incoming_idr, false);
01078             break;
01079 
01080         case MLE_COMMAND_ACCEPT_AND_REQUEST:
01081         case MLE_COMMAND_ACCEPT:
01082             if (mle_msg->message_type == MLE_COMMAND_ACCEPT_AND_REQUEST) {
01083                 if (mle_validate_6lowpan_link_request_message(mle_msg->data_ptr, mle_msg->data_length, &mle_challenge) != 0) {
01084                     return;
01085                 }
01086             }
01087             //Validate Response First
01088             responseId = mle_tlv_validate_response(mle_msg->data_ptr, mle_msg->data_length);
01089             if (responseId == 0) {
01090                 return;
01091             }
01092 
01093             tr_debug("Accept & Request");
01094             entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
01095             if (!entry_temp) {
01096                 // If there is space for neighbors try to allocate new entry
01097                 if (mle_6lowpan_neighbor_limit_check(mle_msg, true)) {
01098                     entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, true, NULL);
01099                 }
01100             }
01101 
01102             if (!entry_temp) {
01103                 tr_debug("Reject by no space");
01104                 mle_service_reject_message_build(cur->id, mle_msg->packet_src_address, false);
01105                 return;
01106             }
01107 
01108             //Init mle security counters
01109 
01110             //Response state set now timeout know positive state
01111             mle_service_set_msg_response_true(responseId);
01112             entry_temp->connected_device  = 1;
01113 
01114             mac_data_poll_protocol_poll_mode_decrement(cur);
01115 
01116             //Read Source address and Challenge
01117             mle_neigh_time_and_mode_update(entry_temp, mle_msg);
01118             if (mle_msg->message_type == MLE_COMMAND_ACCEPT_AND_REQUEST) {
01119                 // If no global address set priority (bootstrap ongoing)
01120                 if (!cur->global_address_available) {
01121                     entry_temp->link_role  = PRIORITY_PARENT_NEIGHBOUR;
01122                 }
01123 
01124                 mle_neigh_entry_update_by_mle_tlv_list(cur->id, entry_temp, mle_msg->data_ptr, mle_msg->data_length, cur->mac, own_mac16);
01125                 incoming_idr = mle_calculate_idr(cur->id, mle_msg, entry_temp);
01126                 uint8_t priority = (entry_temp->link_role  == PRIORITY_PARENT_NEIGHBOUR);
01127                 mle_router_accept_request_build(cur, mle_msg, mle_challenge.dataPtr, mle_challenge.tlvLen, MLE_COMMAND_ACCEPT, incoming_idr, priority);
01128             } else {
01129                 mle_neigh_entry_update_by_mle_tlv_list(cur->id, entry_temp, mle_msg->data_ptr, mle_msg->data_length, cur->mac, own_mac16);
01130                 incoming_idr = mle_calculate_idr(cur->id, mle_msg, entry_temp);
01131             }
01132             mle_neigh_entry_frame_counter_update(entry_temp, mle_msg->data_ptr, mle_msg->data_length, cur, security_headers->KeyIndex);
01133             // If MLE frame counter was invalid update its value since three way handshake is complete
01134             if (security_headers->invalid_frame_counter) {
01135                 mle_service_frame_counter_entry_add(interface_id, entry_temp->index , security_headers->frameCounter);
01136             }
01137             break;
01138 
01139         case MLE_COMMAND_REJECT:
01140             if (security_headers->invalid_frame_counter) {
01141                 return;
01142             }
01143             protocol_6lowpan_link_reject_handler(cur, mle_msg->packet_src_address);
01144             break;
01145 
01146         case MLE_COMMAND_ADVERTISEMENT:
01147             tr_info("Received MLE Advertisement from %s", trace_ipv6(mle_msg->packet_src_address));
01148             if (!cur->global_address_available || security_headers->invalid_frame_counter) {
01149                 tr_error("MLE adv: Invalid frame counter: %s", security_headers->invalid_frame_counter ? "true" : "false");
01150                 return;
01151             } else {
01152                 uint8_t drop_advertisment = 0;
01153 
01154                 if (mle_tlv_option_discover(mle_msg->data_ptr, mle_msg->data_length, MLE_TYPE_MODE, &mle_tlv_info) > 0) {
01155                     t_ptr = mle_tlv_info.dataPtr;
01156                     mode = *t_ptr;
01157                 }
01158                 entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
01159                 if (!entry_temp) {
01160                     if ((mode & MLE_DEV_MASK) == MLE_FFD_DEV) {
01161                         // If there is space for neighbors synchronizes to new router
01162                         if (mle_6lowpan_neighbor_limit_check(mle_msg, false)) {
01163                             // Checks blacklist
01164                             if (blacklist_reject(mle_msg->packet_src_address)) {
01165                                 return;
01166                             }
01167                             incoming_idr = mle_calculate_idr(interface_id, mle_msg, NULL);
01168                             protocol_6lowpan_router_synch_to_new_router(cur, mle_msg->packet_src_address, 0, false);
01169                         }
01170                     }
01171                     tr_error("MLE adv: No MLE entry");
01172                     return;
01173                 }
01174 
01175                 //Verify Own Address
01176                 drop_advertisment = 1;
01177                 //Disvover own address only when we are aloocated address
01178                 if (mle_tlv_option_discover(mle_msg->data_ptr, mle_msg->data_length, MLE_TYPE_LINK_QUALITY, &mle_tlv_info) > 0) {
01179                     uint8_t link_flags;
01180                     if (mle_tlv_info.tlvLen > 0) {
01181                         link_flags = *(mle_tlv_info.dataPtr);
01182                         if (mle_link_quality_tlv_parse(cur->mac, mac_helper_mac16_address_get(cur), mle_tlv_info.dataPtr, mle_tlv_info.tlvLen, NULL, NULL)) {
01183                             drop_advertisment = 0;
01184                         }
01185 
01186                         if (drop_advertisment) {
01187                             if (link_flags & 0x80) {
01188                                 //Total Entry at messgae
01189                                 //Possible remove
01190                                 if ((mode & MLE_DEV_MASK) == MLE_RFD_DEV) {
01191                                     //Remove Entry
01192                                     mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), entry_temp);
01193                                     tr_error("MLE adv: Own address not found");
01194                                     return;
01195                                 }
01196                             }
01197                         }
01198                     }
01199                 }
01200 
01201                 //UPDATE
01202                 mle_neigh_entry_update_by_mle_tlv_list(cur->id, entry_temp, mle_msg->data_ptr, mle_msg->data_length, cur->mac, own_mac16);
01203                 mle_neigh_entry_frame_counter_update(entry_temp, mle_msg->data_ptr, mle_msg->data_length, cur, security_headers->KeyIndex);
01204                 if (entry_temp->connected_device ) {
01205                     mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, entry_temp->link_lifetime );
01206                 }
01207             }
01208             break;
01209 
01210         default:
01211             break;
01212     }
01213 }
01214 
01215 int8_t arm_6lowpan_mle_service_ready_for_security_init(protocol_interface_info_entry_t *cur)
01216 {
01217     //Verify MLE Service
01218     if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_MLE) {
01219         //validate MLE service
01220         if (!mle_service_interface_registeration_validate(cur->id)) {
01221             //Register
01222             if (mle_service_interface_register(cur->id, cur, mle_6lowpan_message_handler, cur->mac, 8) != 0) {
01223                 tr_error("Mle Service init Fail");
01224                 return -1;
01225             }
01226             if (mle_6lowpan_data) {
01227                 if (mle_service_interface_token_bucket_settings_set(cur->id, mle_6lowpan_data->token_bucket_size,
01228                                                                     mle_6lowpan_data->token_bucket_rate, mle_6lowpan_data->token_bucket_count) < 0) {
01229                     return -1;
01230                 }
01231                 mle_service_set_frame_counter_check(true);
01232                 mle_service_set_accept_invalid_frame_counter(true);
01233             }
01234         }
01235     }
01236     return 0;
01237 }
01238 
01239 static uint8_t protocol_6lowpan_mle_data_allocate(void)
01240 {
01241     if (mle_6lowpan_data) {
01242         return 0;
01243     }
01244 
01245     mle_6lowpan_data = ns_dyn_mem_alloc(sizeof(mle_6lowpan_data_t));
01246 
01247     if (!mle_6lowpan_data) {
01248         return 0;
01249     }
01250 
01251     mle_6lowpan_data->router_lifetime = MLE_ROUTER_DEFAULT_LIFETIME;
01252     mle_6lowpan_data->host_lifetime = MLE_ROUTER_HOST_LIFETIME;
01253     mle_6lowpan_data->nbr_of_neigh_lower_threshold = MLE_NBR_OF_NEIGHBOR_MAX_LIMIT;
01254     mle_6lowpan_data->nbr_of_neigh_upper_threshold = MLE_NBR_OF_NEIGHBOR_LOWER_THRESHOLD;
01255     mle_6lowpan_data->nbr_of_neigh_max = MLE_NBR_OF_NEIGHBOR_UPPER_THRESHOLD;
01256 
01257     mle_6lowpan_data->token_bucket_size = MLE_TOKEN_BUCKET_SIZE;
01258     mle_6lowpan_data->token_bucket_rate = MLE_TOKEN_BUCKET_RATE;
01259     mle_6lowpan_data->token_bucket_count = MLE_TOKEN_BUCKET_COUNT;
01260 
01261     mle_6lowpan_data->link_req_token_bucket = MLE_LINK_REQ_TOKEN_BUCKET_SIZE;
01262 
01263     return 0;
01264 }
01265 
01266 mle_6lowpan_data_t *protocol_6lowpan_mle_data_get(void)
01267 {
01268     return mle_6lowpan_data;
01269 }
01270 
01271 static void protocol_6lowpan_mle_purge_neighbors(struct protocol_interface_info_entry *cur_interface, uint8_t entry_count, uint8_t force_priority)
01272 {
01273 
01274     uint8_t count = 0;
01275     uint8_t ll64[16];
01276 
01277     if (!cur_interface) {
01278         return;
01279     }
01280     mac_neighbor_table_list_t *mac_table_list = &cur_interface->mac_parameters->mac_neighbor_table->neighbour_list;
01281 
01282     entry_count = protocol_6lowpan_mle_order_last_entries(cur_interface->id, mac_table_list, entry_count);
01283 
01284     ns_list_foreach_reverse_safe(mac_neighbor_table_entry_t, entry, mac_table_list) {
01285         if (++count > entry_count) {
01286             break;
01287         }
01288 
01289         if (!force_priority) {
01290             if (entry->link_role ==  PRIORITY_PARENT_NEIGHBOUR || entry->link_role == CHILD_NEIGHBOUR) {
01291                 break;
01292             }
01293         }
01294 
01295         memcpy(ll64, ADDR_LINK_LOCAL_PREFIX, 8);
01296         memcpy(&ll64[8], entry->mac64, 8);
01297         ll64[8] ^= 2;
01298 
01299         tr_debug("MLE purge");
01300 
01301         // Sends REJECT
01302         mle_service_reject_message_build(cur_interface->id, ll64, false);
01303         mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur_interface), entry);
01304 
01305         // Adds purged neighbor to blacklist so that it is not added right away back from advertisement
01306         blacklist_update(ll64, false);
01307     }
01308 }
01309 
01310 static uint8_t protocol_6lowpan_mle_order_last_entries(int8_t interface_id, mac_neighbor_table_list_t *mac_neigh_table, uint8_t entry_count)
01311 {
01312     mac_neighbor_table_entry_t *last;
01313     mac_neighbor_table_entry_t *first_ordered = NULL;
01314     etx_storage_t *etx_last, *etx_cur;
01315     uint8_t count = 0;
01316     do {
01317         last = NULL;
01318 
01319         ns_list_foreach(mac_neighbor_table_entry_t, entry, mac_neigh_table) {
01320 
01321             if (entry == first_ordered) {
01322                 break;
01323             }
01324 
01325             if (last == NULL) {
01326                 last = entry;
01327                 continue;
01328             }
01329 
01330             if (entry->link_role > last->link_role ) { //Bigger link role is allways better
01331                 continue;
01332             } else if (entry->link_role == last->link_role ) {
01333                 // Compare ETX when Link role is same
01334                 etx_cur = etx_storage_entry_get(interface_id, entry->index);
01335                 etx_last = etx_storage_entry_get(interface_id, last->index );
01336                 if (etx_cur && etx_last && etx_cur->etx <= etx_last->etx) {
01337                     continue;
01338                 }
01339             }
01340             last = entry;
01341         }
01342 
01343         // Sets last to end of list
01344         if (last) {
01345             ns_list_remove(mac_neigh_table, last);
01346 
01347             if (first_ordered) {
01348                 ns_list_add_before(mac_neigh_table, first_ordered, last);
01349             } else {
01350                 ns_list_add_to_end(mac_neigh_table, last);
01351             }
01352 
01353             first_ordered = last;
01354 
01355             count++;
01356 
01357             if (count == entry_count) {
01358                 break;
01359             }
01360             // If no lasts anymore then exits
01361         } else {
01362             break;
01363         }
01364 
01365     } while (true);
01366 
01367     return count;
01368 }
01369 
01370 static int8_t arm_6lowpan_bootstrap_down(protocol_interface_info_entry_t *cur)
01371 {
01372     if (!cur || !(cur->lowpan_info & INTERFACE_NWK_ACTIVE)) {
01373         return -1;
01374     }
01375     mac_data_poll_disable(cur);
01376     /* Save security counter values to RAM and NVM */
01377     if (cur->nwk_wpan_nvm_api) {
01378         cur->nwk_wpan_nvm_api->nvm_params_update_cb(cur->nwk_wpan_nvm_api, true);
01379     }
01380     cur->if_lowpan_security_params->mle_security_frame_counter = mle_service_security_get_frame_counter(cur->id);
01381     mle_service_interface_receiver_handler_update(cur->id, mle_6lowpan_message_handler);
01382     return nwk_6lowpan_down(cur);
01383 }
01384 #ifdef HAVE_6LOWPAN_ND
01385 
01386 static void lowpan_mle_receive_security_bypass_cb(int8_t interface_id, mle_message_t *mle_msg)
01387 {
01388     (void) interface_id;
01389 #ifdef PANA
01390     protocol_interface_info_entry_t *interface = mle_msg->interface_ptr;
01391     //Accept Only Link Reject
01392     if (mle_msg->message_type == MLE_COMMAND_REJECT) {
01393 
01394         if ((interface->lowpan_info & (INTERFACE_NWK_BOOTSRAP_ACTIVE | INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION)) != (INTERFACE_NWK_BOOTSRAP_ACTIVE | INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION)) {
01395             return;
01396         }
01397 
01398         if (protocol_6lowpan_interface_compare_cordinator_netid(interface, mle_msg->packet_src_address + 8) != 0) {
01399             return;
01400         }
01401 
01402         if (interface->nwk_bootstrap_state != ER_PANA_AUTH) {
01403             return;
01404         }
01405 
01406         //Stop Pana and call ECC
01407         tr_debug("MLE Link reject from cordinator");
01408         pana_reset_client_session();
01409         bootsrap_next_state_kick(ER_PANA_AUTH_ERROR, interface);
01410     }
01411 #else
01412     (void)mle_msg;
01413 #endif
01414 }
01415 
01416 void arm_6lowpan_security_init_ifup(protocol_interface_info_entry_t *cur)
01417 {
01418     if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_MLE) {
01419 
01420         mle_service_security_init(cur->id, cur->if_lowpan_security_params->security_level, cur->if_lowpan_security_params->mle_security_frame_counter,  NULL, protocol_6lowpan_mle_service_security_notify_cb);
01421         switch (cur->if_lowpan_security_params->nwk_security_mode) {
01422 
01423             case NET_SEC_MODE_PSK_LINK_SECURITY:
01424 
01425                 mle_service_security_set_security_key(cur->id, cur->if_lowpan_security_params->psk_key_info.security_key, cur->if_lowpan_security_params->psk_key_info.key_id, true);
01426                 mle_service_security_set_frame_counter(cur->id, cur->if_lowpan_security_params->mle_security_frame_counter);
01427                 break;
01428             case NET_SEC_MODE_PANA_LINK_SECURITY:
01429                 mle_service_interface_receiver_bypass_handler_update(cur->id, lowpan_mle_receive_security_bypass_cb);
01430                 break;
01431             default:
01432                 break;
01433         }
01434     }
01435 
01436     cur->mac_parameters->mac_key_id_mode = MAC_KEY_ID_MODE_IDX;
01437     cur->mac_parameters->mac_configured_sec_level = cur->if_lowpan_security_params->security_level;
01438     switch (cur->if_lowpan_security_params->nwk_security_mode) {
01439 
01440         case NET_SEC_MODE_PANA_LINK_SECURITY:
01441             cur->lowpan_info |= (INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION);
01442             break;
01443 
01444         case NET_SEC_MODE_PSK_LINK_SECURITY:
01445             mac_helper_security_default_key_set(cur, cur->if_lowpan_security_params->psk_key_info.security_key, cur->if_lowpan_security_params->psk_key_info.key_id, MAC_KEY_ID_MODE_IDX);
01446         /* fall through */
01447         default:
01448             cur->lowpan_info &= ~INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION;
01449             break;
01450     }
01451 }
01452 #endif
01453 
01454 static int8_t arm_6lowpan_bootstrap_up(protocol_interface_info_entry_t *cur)
01455 {
01456     int8_t ret_val = -1;
01457     if ((cur->configure_flags & INTERFACE_SETUP_MASK) != INTERFACE_SETUP_READY) {
01458         tr_debug("Interface not yet fully configured");
01459         ret_val = -5;
01460     } else {
01461 
01462         //Verify MLE Service
01463         if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_MLE) {
01464             //validate MLE service
01465             if (!mle_service_interface_registeration_validate(cur->id)) {
01466                 //Register
01467 
01468                 if (mle_service_interface_register(cur->id, cur, mle_6lowpan_message_handler, cur->mac, 8) != 0) {
01469                     tr_error("Mle Service init Fail");
01470                     return -1;
01471                 }
01472             }
01473 
01474             if (mle_6lowpan_data) {
01475                 if (mle_service_interface_token_bucket_settings_set(cur->id, mle_6lowpan_data->token_bucket_size,
01476                                                                     mle_6lowpan_data->token_bucket_rate, mle_6lowpan_data->token_bucket_count) < 0) {
01477                     tr_error("Mle Service tokens set Fail");
01478                     return -1;
01479                 }
01480                 mle_service_set_frame_counter_check(true);
01481                 mle_service_set_accept_invalid_frame_counter(true);
01482             }
01483         }
01484 
01485         arm_6lowpan_security_init_ifup(cur);
01486 
01487         //SET 6lowpan default here
01488         mac_helper_mac_mlme_max_retry_set(cur->id, LOWPAN_MAX_FRAME_RETRIES);
01489 
01490         addr_interface_set_ll64(cur, NULL);
01491         if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_ROUTER) {
01492             cur->lowpan_info |= INTERFACE_NWK_ROUTER_DEVICE;
01493             //rpl_control_set_domain_on_interface(cur, protocol_6lowpan_rpl_domain, true);
01494             icmpv6_radv_enable(cur);
01495         }
01496         ret_val = nwk_6lowpan_up(cur);
01497     }
01498     return ret_val;
01499 }
01500 #endif
01501 
01502 void arm_6lowpan_bootstrap_init(protocol_interface_info_entry_t *cur)
01503 {
01504     //Init 6lowpan Bootsrap
01505     icmp_nd_routers_init();
01506     cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ACTIVE;
01507     cur->lowpan_info &= ~INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY;
01508     bootsrap_next_state_kick(ER_SCAN, cur);
01509     mac_helper_mac16_address_set(cur, 0xffff);
01510 }
01511 
01512 #ifdef HAVE_6LOWPAN_ND
01513 static void arm_6lowpan_bootstrap_functions_set(protocol_interface_info_entry_t *cur)
01514 {
01515     cur->if_up = arm_6lowpan_bootstrap_up;
01516     cur->if_down = arm_6lowpan_bootstrap_down;
01517 }
01518 
01519 static uint8_t protocol_6lowpan_analyze_beacon_payload(uint8_t *ptr, uint8_t len, protocol_interface_info_entry_t *cur)
01520 {
01521     (void)len;
01522     nwk_filter_params_s *filter = &(cur->mac_parameters->nwk_filter_params);
01523 
01524     if (*ptr == filter->beacon_protocol_id_filter || filter->beacon_protocol_id_filter == 0xff) {
01525         ptr++;
01526         if (filter->nwk_active_scan_level == 2) {
01527             if ((*ptr & 1)) {
01528                 if (filter->beacon_nwk_id_filter) {
01529                     ptr++;
01530                     if (memcmp(filter->beacon_nwk_id_filter, ptr, 16)) {
01531                         tr_debug("NWK ID filter");
01532                         return 0;
01533                     }
01534                 }
01535                 return 1;
01536             }
01537         } else {
01538             return 1;
01539         }
01540     }
01541 
01542     return 0;
01543 }
01544 
01545 int8_t arm_network_processor_up(protocol_interface_info_entry_t *cur)
01546 {
01547     int8_t ret_val = -1;
01548     if ((cur->configure_flags & INTERFACE_SETUP_NETWORK_DRIVER_MASK) != INTERFACE_SETUP_NETWORK_DRIVER_READY) {
01549         tr_debug("Interface not yet fully configured\n");
01550         ret_val = -5;
01551     } else {
01552         protocol_6lowpan_register_handlers(cur);
01553         mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, true);
01554         mac_helper_default_security_level_set(cur, SEC_NONE);
01555 
01556         if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_RF_SNIFFER) {
01557             mac_helper_pib_boolean_set(cur, macAssociationPermit, false);
01558             mac_helper_pib_boolean_set(cur, macPromiscuousMode, true);
01559             lowpan_bootstrap_pan_control(cur, false);
01560 
01561         } else if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_RF_ACCESPOINT) {
01562             // Updates beacon
01563             beacon_join_priority_update(cur->id);
01564             mac_helper_pib_boolean_set(cur, macAssociationPermit, true);
01565             net_load_balance_internal_state_activate(cur, true);
01566         }
01567 
01568         cur->nwk_bootstrap_state = ER_BOOTSRAP_DONE;
01569         cur->interface_mode = INTERFACE_UP;
01570         cur->nwk_mode = ARM_NWK_RAW_PHY_MODE;
01571         cur->lowpan_info |= (INTERFACE_NWK_ACTIVE | INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY);
01572         cur->bootsrap_state_machine_cnt = 0;
01573         nwk_bootsrap_state_update(ARM_NWK_BOOTSTRAP_READY, cur);
01574 
01575         ret_val = 0;
01576     }
01577     return ret_val;
01578 }
01579 
01580 static void arm_6lowpan_security_key_update_cb(protocol_interface_info_entry_t *cur, const mlme_security_t *security_params)
01581 {
01582     if (cur->mac_parameters->mac_next_key_index && (security_params->KeyIndex == cur->mac_parameters->mac_next_key_index)) {
01583         tr_debug("Trig Next Key");
01584         mac_helper_security_key_swap_next_to_default(cur);
01585         mle_service_security_key_trig(cur->id, security_params->KeyIndex);
01586         if (cur->nwk_wpan_nvm_api) {
01587             cur->nwk_wpan_nvm_api->nvm_params_update_cb(cur->nwk_wpan_nvm_api, true);
01588         }
01589     }
01590 }
01591 
01592 static void lowpan_neighbor_entry_remove_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data)
01593 {
01594 
01595     protocol_interface_info_entry_t *cur_interface = user_data;
01596     lowpan_adaptation_remove_free_indirect_table(cur_interface, entry_ptr);
01597     // Sleepy host
01598     if (cur_interface->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE) {
01599         mac_data_poll_protocol_poll_mode_decrement(cur_interface);
01600     }
01601 
01602     protocol_6lowpan_priority_neighbor_remove(cur_interface, entry_ptr);
01603 
01604     if (entry_ptr->ffd_device ) {
01605         protocol_6lowpan_release_short_link_address_from_neighcache(cur_interface, entry_ptr->mac16 );
01606         protocol_6lowpan_release_long_link_address_from_neighcache(cur_interface, entry_ptr->mac64 );
01607     }
01608     mac_helper_devicetable_remove(cur_interface->mac_api, entry_ptr->index , entry_ptr->mac64 );
01609     //Removes ETX neighbor
01610     etx_neighbor_remove(cur_interface->id, entry_ptr->index );
01611     //Remove MLE frame counter info
01612     mle_service_frame_counter_entry_delete(cur_interface->id, entry_ptr->index );
01613 
01614 }
01615 
01616 
01617 static bool lowpan_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data)
01618 {
01619 
01620     // Sleepy host
01621     protocol_interface_info_entry_t *cur_interface = user_data;
01622 
01623     if (cur_interface->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) {
01624         //Trig middle way challenge if Broadcast message  have been missed
01625         if (!entry_ptr->ffd_device ) {
01626             return false; //End device must do this
01627         }
01628 
01629         if (entry_ptr->lifetime  > (entry_ptr->link_lifetime  / 2)) {
01630             return false; //Trig only when midway is overed
01631         }
01632         return protocol_6lowpan_router_challenge(cur_interface, entry_ptr->mac64 );
01633     }
01634 
01635     if (entry_ptr->link_role  != PRIORITY_PARENT_NEIGHBOUR) {
01636         return false; //Do not never challenge than priority parent
01637     }
01638 
01639     if (cur_interface->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE) {
01640         return false; //Sleepy end device should not never challenge
01641     }
01642 
01643     if (entry_ptr->lifetime   > MLE_TABLE_CHALLENGE_TIMER) {
01644         return false;
01645     }
01646 
01647     return protocol_6lowpan_host_challenge(cur_interface, entry_ptr->mac64 );
01648 }
01649 
01650 
01651 int8_t arm_6lowpan_bootstarp_bootstrap_set(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode, net_6lowpan_mode_extension_e net_6lowpan_mode_extension)
01652 {
01653     int8_t ret_val = -1;
01654     bool enable_mle_protocol = true;
01655     protocol_interface_info_entry_t *cur;
01656 
01657     cur = protocol_stack_interface_info_get_by_id(interface_id);
01658     if (!cur) {
01659         return -1;
01660     }
01661 
01662     arm_6lowpan_bootstrap_functions_set(cur);
01663     cur->mac_parameters->beacon_ind = protocol_6lowpan_analyze_beacon_payload;
01664 
01665     mac_beacon_link_beacon_join_priority_tx_callback_set(cur->id, protocol_6lowpan_beacon_join_priority_tx);
01666     mac_beacon_link_beacon_compare_rx_callback_set(cur->id, protocol_6lowpan_beacon_compare_rx);
01667 
01668     if (net_6lowpan_mode_extension == NET_6LOWPAN_ND_WITHOUT_MLE) {
01669         enable_mle_protocol = false;
01670     }
01671 
01672     cur->mac_security_key_usage_update_cb = arm_6lowpan_security_key_update_cb;
01673     //Allocate MLE class here
01674     //Deallocate old here
01675     mac_neighbor_table_delete(mac_neighbor_info(cur));
01676     mac_description_storage_size_t buffer;
01677     //Read MAC device table sizes
01678     if (cur->mac_api->mac_storage_sizes_get(cur->mac_api, &buffer) != 0) {
01679         return -1;
01680     }
01681 
01682     mac_neighbor_info(cur) = mac_neighbor_table_create(buffer.device_decription_table_size, lowpan_neighbor_entry_remove_notify
01683                                                        , lowpan_neighbor_entry_nud_notify, cur);
01684     if (!mac_neighbor_info(cur)) {
01685         return -1;
01686     }
01687 
01688     if (enable_mle_protocol) {
01689         if (mle_service_frame_counter_table_allocate(interface_id, buffer.device_decription_table_size)) {
01690             return -1;
01691         }
01692 
01693         if (!etx_storage_list_allocate(cur->id, buffer.device_decription_table_size)) {
01694             return -1;
01695         }
01696 
01697         lowpan_adaptation_interface_etx_update_enable(cur->id);
01698     }
01699 
01700     mle_service_interface_unregister(cur->id);
01701 
01702     if (bootstrap_mode == NET_6LOWPAN_NETWORK_DRIVER || bootstrap_mode == NET_6LOWPAN_SNIFFER) {
01703         enable_mle_protocol = false;
01704         cur->if_up = arm_network_processor_up;
01705         if (bootstrap_mode == NET_6LOWPAN_NETWORK_DRIVER) {
01706             cur->bootsrap_mode = ARM_NWK_BOOTSRAP_MODE_6LoWPAN_RF_ACCESPOINT;
01707             cur->mac_parameters->beacon_ind = NULL; //Drop beacons
01708         } else {
01709             cur->bootsrap_mode = ARM_NWK_BOOTSRAP_MODE_6LoWPAN_RF_SNIFFER;
01710         }
01711         cur->lowpan_info &= ~INTERFACE_NWK_ROUTER_DEVICE;
01712         cur->lowpan_info |= INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE;
01713         arm_nwk_6lowpan_borderrouter_data_free(cur);
01714 
01715         ret_val = 0;
01716         goto bootstrap_finish_check;
01717     } else {
01718         if (enable_mle_protocol) {
01719 #ifdef NO_MLE
01720             return -2;
01721 #else
01722             cur->comm_status_ind_cb = lowpan_comm_status_indication_cb;
01723             if (mle_service_interface_register(cur->id, cur, mle_6lowpan_message_handler, cur->mac, 8) != 0) {
01724                 tr_error("Mle Service init Fail");
01725                 return -1;
01726             }
01727 
01728             if (protocol_6lowpan_mle_data_allocate() != 0) {
01729                 tr_error("MLE data allocate Fail");
01730                 return -1;
01731             }
01732 
01733             if (blacklist_init() != 0) {
01734                 tr_error("Blacklist init Fail");
01735                 return -1;
01736             }
01737 
01738             if (mle_6lowpan_data) {
01739                 if (mle_service_interface_token_bucket_settings_set(cur->id, mle_6lowpan_data->token_bucket_size,
01740                                                                     mle_6lowpan_data->token_bucket_rate, mle_6lowpan_data->token_bucket_count) < 0) {
01741                     tr_error("Mle Service tokens set Fail");
01742                     return -1;
01743                 }
01744                 mle_service_set_frame_counter_check(true);
01745                 mle_service_set_accept_invalid_frame_counter(true);
01746             }
01747 #endif
01748         }
01749 
01750         arm_6lowpan_bootstrap_functions_set(cur);
01751         cur->configure_flags &= ~INTERFACE_BOOTSTRAP_DEFINED;
01752         switch (bootstrap_mode) {
01753             case NET_6LOWPAN_HOST:
01754                 protocol_6lowpan_host_init(cur, false);
01755                 ret_val = 0;
01756                 break;
01757             case NET_6LOWPAN_SLEEPY_HOST:
01758                 protocol_6lowpan_host_init(cur, true);
01759                 ret_val = 0;
01760                 break;
01761 
01762             case NET_6LOWPAN_ROUTER:
01763                 protocol_6lowpan_router_init(cur);
01764                 ret_val = 0;
01765                 break;
01766 
01767             case NET_6LOWPAN_BORDER_ROUTER:
01768                 ret_val = arm_nwk_6lowpan_borderrouter_init(cur);
01769                 cur->mac_parameters->beacon_ind = NULL; //Drop beacons
01770                 break;
01771             default:
01772                 break;
01773 
01774         }
01775     }
01776 
01777 bootstrap_finish_check:
01778     if (ret_val == 0) {
01779         /**
01780          *  Do Thread dealloc
01781          */
01782         thread_info_deallocate(cur);
01783         //ADD RPL Support if supported and device is router
01784 #ifdef HAVE_RPL
01785         /**
01786          *  ADD RPL Flag If device is router
01787          */
01788         if (cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) {
01789             //rpl_control_set_domain_on_interface(cur, protocol_6lowpan_rpl_domain, true);
01790             //rpl_control_set_callback(protocol_6lowpan_rpl_domain, protocol_6lowpan_bootstrap_rpl_callback, NULL, NULL, cur);
01791         }
01792 #endif
01793         cur->configure_flags |= INTERFACE_BOOTSTRAP_DEFINED;
01794         if (enable_mle_protocol) {
01795             cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_MLE;
01796         } else {
01797             cur->lowpan_info &= ~INTERFACE_NWK_BOOTSRAP_MLE;
01798         }
01799     }
01800 
01801     return ret_val;
01802 }
01803 
01804 
01805 static void protocol_6lowpan_bootstrap_icmp_rs_msg_tx(protocol_interface_info_entry_t *cur)
01806 {
01807     buffer_t *buf = icmpv6_build_rs(cur, NULL);
01808 
01809     protocol_push(buf);
01810 }
01811 
01812 void nwk_6lowpan_router_scan_state(protocol_interface_info_entry_t *cur)
01813 {
01814     cur->nwk_rpl_scan_counter = 0;
01815     if (cur->nwk_nd_re_scan_count == 0) {
01816         if (cur->border_router_setup) {
01817             //Activate RS
01818             arm_border_router_ready(cur);
01819         } else {
01820             tr_warn("No ND Router");
01821             nwk_bootsrap_state_update(ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL, cur);
01822         }
01823 
01824     } else {
01825         //Verify is ND Object allocated already
01826         if (!cur->border_router_setup && nd_object_active()) {
01827             tr_debug("Wait response from  ND");
01828         } else {
01829             tr_debug("RS*");
01830             protocol_6lowpan_bootstrap_icmp_rs_msg_tx(cur);
01831             cur->nwk_nd_re_scan_count--;
01832             if (cur->border_router_setup) {
01833                 cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(25, 50);
01834             } else {
01835                 if ((cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) == 0) {
01836                     cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(25, 40);
01837                 } else {
01838                     cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(60, 70);
01839                 }
01840             }
01841         }
01842     }
01843 }
01844 
01845 void nwk_6lowpan_bootstrap_ready(protocol_interface_info_entry_t *cur)
01846 {
01847     if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_ACTIVE) {
01848         uint8_t bootsrap_ready = 0;
01849 
01850         if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION) {
01851 
01852             if (cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) {
01853                 if (pana_ping_notify_msg_tx(cur->mac_parameters->pan_id) == 0) {
01854                     tr_warn("PING TX fail");
01855                 } else {
01856                     bootsrap_ready = 1;
01857                 }
01858 
01859             } else {
01860                 if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_MLE) {
01861 #ifndef NO_MLE
01862                     tr_debug("MLE Parent Advertisment");
01863                     if (protocol_6lowpan_mle_neigh_advertise(cur) == 0) {
01864                         bootsrap_ready = 1;
01865                     } else {
01866                         tr_warn("MLE Host Parent Advert TX fail");
01867                     }
01868 #endif
01869                 } else {
01870                     bootsrap_ready = 1;
01871                 }
01872             }
01873         } else {
01874             bootsrap_ready = 1;
01875 
01876         }
01877         if (bootsrap_ready) {
01878             if (cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) {
01879                 // Updates beacon
01880                 beacon_join_priority_update(cur->id);
01881                 lowpan_bootstrap_pan_control(cur, true);
01882             }
01883             nwk_bootsrap_state_update(ARM_NWK_BOOTSTRAP_READY, cur);
01884         } else {
01885             cur->nwk_bootstrap_state = ER_BOOTSRAP_DONE;
01886             cur->bootsrap_state_machine_cnt = 2;
01887         }
01888     }
01889 }
01890 
01891 void protocol_6lowpan_link_advertise_handle(nd_router_t *cur, protocol_interface_info_entry_t *cur_interface, uint16_t tick)
01892 {
01893     if ((cur_interface->lowpan_info & (INTERFACE_NWK_BOOTSRAP_MLE  | INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY)) == (INTERFACE_NWK_BOOTSRAP_MLE  | INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY)) {
01894 #ifndef NO_MLE
01895         if (cur->mle_advert_timer) {
01896             if (cur->mle_advert_timer > tick) {
01897                 cur->mle_advert_timer -= tick;
01898 
01899             } else {
01900                 if (protocol_6lowpan_mle_neigh_advertise(cur_interface) == 0) {
01901 
01902                     if (cur_interface->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE) {
01903                         cur->mle_advert_timer = 0;
01904                     } else {
01905                         cur->mle_advert_timer = 155;
01906 
01907                         if (mle_6lowpan_data) {
01908                             uint16_t period = mle_6lowpan_data->router_lifetime / 4;
01909                             if (period > 640) {
01910                                 period = 640;
01911                             }
01912                             period *= 10; //seconds ticks --> 100ms ticks
01913                             //set 0.9 - 1.1 * period
01914                             cur->mle_advert_timer = randLIB_randomise_base(period, LOWPAN_RAND_LOW, LOWPAN_RAND_HIGH);
01915                         }
01916                     }
01917                 } else {
01918                     cur->mle_advert_timer = 2;
01919                 }
01920 
01921                 if (cur->mle_purge_timer) {
01922                     cur->mle_purge_timer -= 1;
01923                 } else {
01924                     if (mle_6lowpan_data && mle_6lowpan_data->nbr_of_neigh_max != 0) {
01925                         uint16_t mle_neigh_cnt = mle_class_active_neigh_counter(cur_interface);
01926                         if (mle_neigh_cnt > (mle_6lowpan_data->nbr_of_neigh_max - MLE_NEIGHBOR_PURGE_NBR)) {
01927                             protocol_6lowpan_mle_purge_neighbors(cur_interface, MLE_NEIGHBOR_PURGE_NBR, true);
01928                         }
01929 
01930                         if (mle_neigh_cnt > (mle_6lowpan_data->nbr_of_neigh_upper_threshold - MLE_NEIGHBOR_PURGE_NBR)) {
01931                             protocol_6lowpan_mle_purge_neighbors(cur_interface, MLE_NEIGHBOR_PURGE_NBR, false);
01932                         }
01933 
01934                         uint16_t mle_purge_timer;
01935                         /* From 1.0 to 1.5 * MLE_NEIGHBOR_PURGE_TIMER */
01936                         mle_purge_timer = randLIB_randomise_base(MLE_NEIGHBOR_PURGE_TIMER_TIMEOUT, 0x8000, 0xC000);
01937                         cur->mle_purge_timer = mle_purge_timer;
01938                     }
01939                 }
01940                 // Updates blacklist timer
01941                 blacklist_ttl_update(1);
01942             }
01943         }
01944 #endif
01945     } else {
01946         cur->mle_advert_timer = 0;
01947     }
01948 }
01949 
01950 static void protocol_6lowpan_nd_ready(protocol_interface_info_entry_t *cur)
01951 {
01952     if ((cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_ACTIVE)) {
01953         tr_debug("ND BS ready");
01954         bootsrap_next_state_kick(ER_BIND_COMP, cur);
01955         clear_power_state(ICMP_ACTIVE);
01956         cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY;
01957     } else {
01958         tr_debug("RE ND ready");
01959         clear_power_state(ICMP_ACTIVE);
01960         mac_data_poll_protocol_poll_mode_disable(cur);
01961         //TRIG MLE Challenge for Normal Host
01962         if ((cur->lowpan_info & (INTERFACE_NWK_ROUTER_DEVICE | INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE | INTERFACE_NWK_BOOTSRAP_MLE)) == INTERFACE_NWK_BOOTSRAP_MLE) {
01963             //TRIG Only Normal Host
01964 #ifndef NO_MLE
01965             //GET Cordinator MLE Entry
01966             addrtype_t addrType;
01967             uint8_t tempAddr[8];
01968             addrType = mac_helper_coordinator_address_get(cur, tempAddr);
01969             mac_neighbor_table_entry_t *neig_info = mac_neighbor_table_address_discover(mac_neighbor_info(cur), tempAddr, addrType);
01970 
01971             if (neig_info) {
01972                 if (neig_info->lifetime  > MLE_TABLE_CHALLENGE_TIMER) {
01973                     neig_info->lifetime   = (MLE_TABLE_CHALLENGE_TIMER + 1);
01974                 }
01975             }
01976 #endif
01977         }
01978     }
01979 }
01980 
01981 static void protocol_6lowpan_address_reg_ready(protocol_interface_info_entry_t *cur_interface)
01982 {
01983     nd_router_t *cur;
01984     cur = nd_get_object_by_nwk_id(cur_interface->nwk_id);
01985 
01986     if (!cur) {
01987         return;
01988     }
01989 
01990     cur->nd_timer = 10;
01991     cur->ns_forward_timer = 0;
01992 
01993     uint16_t mle_timer = 0;
01994     protocol_6lowpan_nd_ready(cur_interface);
01995     if (cur_interface->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) {
01996         addr_add_router_groups(cur_interface);
01997         addr_add_group(cur_interface, ADDR_REALM_LOCAL_ALL_ROUTERS);
01998         icmpv6_radv_enable(cur_interface);
01999         icmpv6_restart_router_advertisements(cur_interface, cur->border_router);
02000         /* Stop the ND revalidate timer - this means we don't do RS again */
02001         cur->nd_re_validate = 0;
02002         mle_timer = 300;
02003     } else {
02004         if (cur_interface->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE) {
02005             mac_data_poll_protocol_poll_mode_decrement(cur_interface);
02006             mle_timer = 20;
02007         } else {
02008             mle_timer = 155;
02009         }
02010     }
02011     if (cur_interface->lowpan_info & INTERFACE_NWK_BOOTSRAP_MLE) {
02012         if (cur->mle_advert_timer == 0) {
02013             cur->mle_advert_timer = mle_timer;
02014             cur->mle_purge_timer = MLE_NEIGHBOR_PURGE_TIMER_TIMEOUT;
02015         }
02016     } else {
02017         cur->mle_advert_timer = 0;
02018     }
02019 }
02020 
02021 void protocol_6lowpan_bootstrap_nd_ready(protocol_interface_info_entry_t *cur_interface)
02022 {
02023 
02024     tr_debug("ND Ready");
02025 
02026 
02027 
02028     if (cur_interface->lowpan_address_mode == NET_6LOWPAN_GP64_ADDRESS) {
02029         protocol_6lowpan_address_reg_ready(cur_interface);
02030     } else {
02031         //Here we need to verify address mode
02032         tr_debug("Synch MAC16 with parent");
02033         if (protocol_6lowpan_parent_address_synch(cur_interface, true) != 0) {
02034             nwk_bootsrap_state_update(ARM_NWK_NWK_CONNECTION_DOWN, cur_interface);
02035         }
02036     }
02037 
02038 
02039 }
02040 
02041 #ifdef HAVE_RPL
02042 
02043 static void protocol_6lowpan_bootstrap_rpl_callback(rpl_event_t event, void *handle)
02044 {
02045 
02046     protocol_interface_info_entry_t *cur = handle;
02047     if (!cur->rpl_domain || cur->interface_mode != INTERFACE_UP) {
02048         return;
02049     }
02050     switch (event) {
02051         case RPL_EVENT_DAO_DONE:
02052             if ((cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_ACTIVE)) {
02053                 bootsrap_next_state_kick(ER_BOOTSRAP_DONE, cur);
02054                 clear_power_state(ICMP_ACTIVE);
02055             } else if (cur->nwk_bootstrap_state == ER_RPL_LOCAL_REPAIR) {
02056                 // Updates beacon
02057                 cur->bootsrap_state_machine_cnt = 0;
02058                 cur->nwk_bootstrap_state = ER_BOOTSRAP_DONE;
02059                 beacon_join_priority_update(cur->id);
02060                 lowpan_bootstrap_pan_control(cur, true);
02061             }
02062             break;
02063 
02064         case RPL_EVENT_LOCAL_REPAIR_START:
02065             if (!(cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_ACTIVE)) {
02066                 tr_error("RPL Local repair started");
02067                 lowpan_bootstrap_pan_control(cur, false);
02068                 cur->bootsrap_state_machine_cnt = 0;
02069                 cur->nwk_bootstrap_state = ER_RPL_LOCAL_REPAIR;
02070             }
02071             break;
02072 
02073         case RPL_EVENT_LOCAL_REPAIR_NO_MORE_DIS:
02074             tr_error("RPL Local repair fail-->interface to idle");
02075             nwk_bootsrap_state_update(ARM_NWK_NWK_CONNECTION_DOWN, cur);
02076             break;
02077         default:
02078             break;
02079     }
02080 }
02081 
02082 /**
02083  * \brief Send ICMP RPL DIS message.
02084  *
02085  * \return 0 , buffer_allocation fail & 1 message sent
02086  */
02087 uint8_t nwk_bootstrap_icmp_rpl_dis_msg_tx(protocol_interface_info_entry_t *cur)
02088 {
02089     if (cur->rpl_domain) {
02090         rpl_control_transmit_dis(cur->rpl_domain, cur, 0, 0, NULL, 0, NULL);
02091         return 1;
02092     }
02093 
02094     return 0;
02095 }
02096 
02097 /**
02098  * \brief Send ICMP RPL DIS message to bootstrap coordinator
02099  *
02100  * \return 0 , buffer_allocation fail & 1 message sent
02101  */
02102 static uint8_t nwk_bootstrap_icmp_rpl_dis_coord_msg_tx(protocol_interface_info_entry_t *cur)
02103 {
02104     if (!cur->rpl_domain) {
02105         return 0;
02106     }
02107 
02108     uint8_t coord_address[16];
02109     if (protocol_6lowpan_interface_get_link_local_cordinator_address(cur, coord_address) != 0) {
02110         tr_debug("Unicast DIS no coord");
02111         return 0;
02112     }
02113 
02114     rpl_control_transmit_dis(cur->rpl_domain, cur, 0, 0, NULL, 0, coord_address);
02115     return 1;
02116 }
02117 
02118 static void nwk_rpl_dio_scan(protocol_interface_info_entry_t *cur)
02119 {
02120     if (cur->nwk_rpl_scan_counter < MAX_MC_DIS_COUNT) {
02121         if (nwk_bootstrap_icmp_rpl_dis_msg_tx(cur)) {
02122             cur->bootsrap_state_machine_cnt = 45 << cur->nwk_rpl_scan_counter;
02123             cur->nwk_rpl_scan_counter++;
02124             tr_debug("MC_DIS\n");
02125             cur->nwk_bootstrap_state = ER_RPL_SCAN;
02126         } else {
02127             cur->bootsrap_state_machine_cnt = 3;
02128         }
02129     } else {
02130         //GivE Up Bootsrap
02131         nwk_bootsrap_state_update(ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL, cur);
02132     }
02133 }
02134 
02135 
02136 void nwk_6lowpan_rpl_router_discover(protocol_interface_info_entry_t *cur)
02137 {
02138     if (cur->rpl_domain) {
02139         tr_debug("MC DIS Force");
02140         if (nwk_bootstrap_icmp_rpl_dis_msg_tx(cur)) {
02141             cur->nwk_bootstrap_state = ER_RPL_SCAN;
02142             cur->bootsrap_state_machine_cnt = 55;
02143         } else {
02144             cur->nwk_bootstrap_state = ER_RPL_MC;
02145             cur->bootsrap_state_machine_cnt = 15;
02146         }
02147     } else {
02148         cur->nwk_bootstrap_state = ER_BOOTSRAP_DONE;
02149         nwk_6lowpan_bootstrap_ready(cur);
02150     }
02151 }
02152 
02153 void nwk_6lowpan_rpl_router_result_check(protocol_interface_info_entry_t *cur)
02154 {
02155     if (cur->rpl_domain) {
02156         if (rpl_control_have_dodag(cur->rpl_domain)) {
02157             tr_debug("UNI DIS");
02158             cur->bootsrap_state_machine_cnt = 0;
02159         } else {
02160             nwk_rpl_dio_scan(cur);
02161         }
02162     } else {
02163         cur->nwk_bootstrap_state = ER_BOOTSRAP_DONE;
02164         nwk_6lowpan_bootstrap_ready(cur);
02165     }
02166 }
02167 #endif
02168 
02169 void nwk_6lowpan_nd_address_registartion_ready(protocol_interface_info_entry_t *cur)
02170 {
02171     tr_debug("ND Ready!!");
02172     cur->nwk_rpl_scan_counter = 0;
02173 
02174 #ifndef NO_MLE
02175     if (cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) {
02176         if (protocol_6lowpan_router_multicast_synch(cur) != 0) {
02177             tr_debug("Router link request start fail");
02178             nwk_bootsrap_state_update(ARM_NWK_NWK_CONNECTION_DOWN, cur);
02179         }
02180 #ifdef HAVE_RPL
02181         if (protocol_6lowpan_rpl_domain) {
02182             // arm_nwk_6lowpan_rpl_dodag_poison from a previous connection may have left force_leaf set
02183             rpl_control_force_leaf(protocol_6lowpan_rpl_domain, false);
02184             rpl_control_set_domain_on_interface(cur, protocol_6lowpan_rpl_domain, true);
02185             rpl_control_set_callback(protocol_6lowpan_rpl_domain, protocol_6lowpan_bootstrap_rpl_callback, NULL, NULL, cur);
02186         }
02187         // Send unicast DIS to coordinator
02188         nwk_bootstrap_icmp_rpl_dis_coord_msg_tx(cur);
02189 #endif /* HAVE_RPL */
02190     } else {
02191         //No point to update link
02192         if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_SLEEPY_HOST || cur->lowpan_address_mode != NET_6LOWPAN_GP64_ADDRESS) {
02193             if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_SLEEPY_HOST) {
02194                 cur->lowpan_info |= INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE;
02195                 tr_debug("Enable Poll state");
02196                 mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, false);
02197                 mac_data_poll_init(cur);
02198                 mac_data_poll_init_protocol_poll(cur);
02199             }
02200             if (protocol_6lowpan_parent_address_synch(cur, false) != 0) {
02201                 nwk_bootsrap_state_update(ARM_NWK_NWK_CONNECTION_DOWN, cur);
02202             }
02203         } else {
02204             cur->nwk_bootstrap_state = ER_BOOTSRAP_DONE;
02205             nwk_6lowpan_bootstrap_ready(cur);
02206         }
02207     }
02208 #else
02209 #ifdef HAVE_RPL
02210     cur->nwk_bootstrap_state = ER_RPL_SCAN;
02211     nwk_6lowpan_rpl_router_result_check(cur);
02212 #else
02213     cur->nwk_bootstrap_state = ER_BOOTSRAP_DONE;
02214     nwk_6lowpan_bootstrap_ready(cur);
02215 #endif
02216 #endif
02217 }
02218 #ifdef PANA
02219 void nwk_6lowpan_pana_key_pull(protocol_interface_info_entry_t *cur)
02220 {
02221     //REG GP16 address
02222     if (pana_ping_notify_msg_tx(cur->mac_parameters->pan_id) == 0) {
02223         tr_warn("PING TX fail");
02224         cur->nwk_bootstrap_state = ER_PANA_PING;
02225         cur->bootsrap_state_machine_cnt = 2;
02226     }
02227 }
02228 #endif
02229 
02230 #ifndef NO_MLE
02231 
02232 #ifdef PANA
02233 void nwk_6lowpan_bootsrap_pana_authentication_cb(bool processSuccesfully, protocol_interface_info_entry_t *cur)
02234 {
02235     if (processSuccesfully) {
02236         bootsrap_next_state_kick(ER_PANA_AUTH_DONE, cur);
02237     } else {
02238         bootsrap_next_state_kick(ER_PANA_AUTH_ERROR, cur);
02239 
02240     }
02241 }
02242 
02243 static void nwk_6lowpan_bootsrap_pana_authentication_start(protocol_interface_info_entry_t *cur)
02244 {
02245     uint8_t temp_coordinator_address[16];
02246     pana_tls_setup_s setup;
02247     sec_suite_t *suite = 0;
02248     tr_debug("Wake Pana by Bootsrap");
02249     protocol_6lowpan_interface_get_link_local_cordinator_address(cur, temp_coordinator_address);
02250     //Release old before copy new
02251     if (cur->pana_sec_info_temp == 0) {
02252         tr_debug("Allocate Pana auth Info");
02253         cur->pana_sec_info_temp = ns_dyn_mem_alloc(sizeof(auth_info_t));
02254     }
02255     if (cur->if_lowpan_security_params->pana_params) {
02256         setup.psk_key_id = cur->if_lowpan_security_params->pana_params->psk_key_id;
02257 
02258         switch (cur->if_lowpan_security_params->pana_params->nwk_chipher_mode) {
02259             case NET_TLS_PSK_CIPHER:        /**< Network Authentication support only PSK */
02260                 setup.security_support = SEC_CIPHERSUITE_PSK;
02261                 break;
02262 
02263             case NET_TLS_ECC_CIPHER:        /**< Network Authentication support only ECC */
02264                 setup.security_support = SEC_CIPHERSUITE_ECC;
02265                 break;
02266             case NET_TLS_PSK_AND_ECC_CIPHER:
02267                 setup.security_support = SEC_CIPHERSUITE_PSK | SEC_CIPHERSUITE_ECC;
02268                 break;
02269         }
02270 
02271         setup.pan_id = cur->mac_parameters->pan_id;
02272         suite = pana_client_init(cur->pana_sec_info_temp, temp_coordinator_address, &setup);
02273 
02274     }
02275     if (suite) {
02276         //SET address
02277         //SET CORD Address
02278         nd_router_t   *object = nd_get_pana_address();
02279         cur->nwk_bootstrap_state = ER_PANA_AUTH;
02280         cur->bootsrap_state_machine_cnt = 0;
02281         if (object) {
02282             icmp_nd_set_nd_def_router_address(suite->session_address, object);
02283 
02284             tr_debug("ND Router adr: %s", trace_ipv6(suite->session_address));
02285 
02286             //SET CORD ADDRESS
02287             if (memcmp(&suite->session_address[8], ADDR_SHORT_ADR_SUFFIC, 6) == 0) {
02288                 mac_helper_coordinator_address_set(cur, ADDR_802_15_4_SHORT , &(suite->session_address[14]));
02289             } else {
02290                 suite->session_address[8] ^= 2;
02291                 mac_helper_coordinator_address_set(cur, ADDR_802_15_4_LONG , &(suite->session_address[8]));
02292                 suite->session_address[8] ^= 2;
02293             }
02294         } else {
02295             tr_debug("Use Mac Coordinator");
02296         }
02297         suite->session_port = UDP_PORT_PANA;
02298         suite->interface = cur;
02299     } else {
02300         cur->nwk_bootstrap_state = ER_PANA_AUTH_ERROR;
02301         cur->bootsrap_state_machine_cnt = 1;
02302     }
02303 }
02304 #endif
02305 
02306 #endif
02307 
02308 static void coordinator_black_list(protocol_interface_info_entry_t *cur)
02309 {
02310     uint8_t coord_pan_address[10];
02311     addrtype_t cord_adr_type = mac_helper_coordinator_address_get(cur, coord_pan_address + 2);
02312 
02313     if (cord_adr_type != ADDR_NONE ) {
02314         uint16_t pana_id = mac_helper_panid_get(cur);
02315         common_write_16_bit(pana_id, coord_pan_address);
02316         if (cord_adr_type == ADDR_802_15_4_SHORT ) {
02317             memset(coord_pan_address + 4, 0, 6);
02318         }
02319 
02320         pan_cordinator_blacklist_pan_set(&cur->pan_cordinator_black_list, coord_pan_address, 300);
02321     }
02322 }
02323 
02324 static void nwk_6lowpan_network_authentication_fail(protocol_interface_info_entry_t *cur)
02325 {
02326     nwk_scan_params_t *scan_params =
02327         &cur->mac_parameters->nwk_scan_params;
02328 
02329     tr_warn("Pana Auhth er");
02330 
02331     scan_params->nwk_cur_active = mac_helper_free_pan_descriptions(scan_params->nwk_cur_active);
02332     //Black List coordinator
02333     coordinator_black_list(cur);
02334 
02335     nwk_bootsrap_state_update(ARM_NWK_AUHTENTICATION_FAIL, cur);
02336 }
02337 
02338 
02339 static void nwk_protocol_network_key_set_from_pana(protocol_interface_info_entry_t *cur)
02340 {
02341     uint8_t *key_ptr = pana_key_get(cur->pana_sec_info_temp->network_key);
02342 
02343     if (key_ptr) {
02344         mac_helper_security_default_key_set(cur, (key_ptr + 16), cur->pana_sec_info_temp->key_id, MAC_KEY_ID_MODE_IDX);
02345         mle_service_security_set_security_key(cur->id, key_ptr, cur->pana_sec_info_temp->key_id, true);
02346         if (cur->nwk_wpan_nvm_api) {
02347             cur->nwk_wpan_nvm_api->nvm_params_update_cb(cur->nwk_wpan_nvm_api, true);
02348         }
02349     }
02350 }
02351 
02352 uint8_t *protocol_6lowpan_mle_service_security_notify_cb(int8_t interface_id, mle_security_event_t event, uint8_t keyId)
02353 {
02354     (void)keyId;
02355     protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(interface_id);
02356     if (!interface) {
02357         return NULL;
02358     }
02359     switch (event) {
02360         case MLE_SEC_MAX_FRAME_COUNTER_REACHED :
02361 
02362             break;
02363 
02364         case MLE_SEC_KEY_UPDATE_NOTIFY :
02365             //Call MAC update
02366             mac_helper_security_key_swap_next_to_default(interface);
02367 
02368             break;
02369 
02370         case MLE_SEC_UNKNOWN_KEY :
02371             break;
02372     }
02373     return NULL;
02374 }
02375 
02376 static void nwk_protocol_network_key_init_from_pana(protocol_interface_info_entry_t *cur)
02377 {
02378     uint8_t *key_ptr = pana_key_get(cur->pana_sec_info_temp->network_key);
02379 
02380     if (key_ptr) {
02381         mac_helper_security_default_key_set(cur, (key_ptr + 16), cur->pana_sec_info_temp->key_id, MAC_KEY_ID_MODE_IDX);
02382         //mac_security_interface_link_frame_counter_reset(cur->id);
02383         mac_helper_default_security_level_set(cur, SEC_ENC_MIC32);
02384         mac_helper_default_security_key_id_mode_set(cur, MAC_KEY_ID_MODE_IDX);
02385         //Init MLE Frame counter and key's and security
02386         mle_service_security_init(cur->id, SEC_ENC_MIC32, cur->if_lowpan_security_params->mle_security_frame_counter,  NULL, protocol_6lowpan_mle_service_security_notify_cb);
02387         mle_service_security_set_security_key(cur->id, key_ptr, cur->pana_sec_info_temp->key_id, true);
02388         mle_service_security_set_frame_counter(cur->id, cur->if_lowpan_security_params->mle_security_frame_counter);
02389     }
02390 }
02391 
02392 static void nwk_6lowpan_network_authentication_done(protocol_interface_info_entry_t *cur)
02393 {
02394     if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_ACTIVE) {
02395         mac_helper_free_scan_confirm(&cur->mac_parameters->nwk_scan_params);
02396 
02397         if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION) {
02398             nwk_protocol_network_key_init_from_pana(cur);
02399         } else {
02400             tr_debug("SET NO security");
02401             mac_helper_default_security_level_set(cur, SEC_NONE);
02402         }
02403 
02404 #ifndef NO_MLE
02405         if (protocol_6lowpan_parent_link_req(cur) != 0) {
02406             tr_debug("Link request start fail");
02407         }
02408 #else
02409         pan_coordinator_blacklist_free(&cur->pan_cordinator_black_list);
02410         cur->nwk_bootstrap_state = ER_SCAN;
02411         nwk_6lowpan_router_scan_state(cur);
02412 #endif
02413     } else {
02414         mac_data_poll_protocol_poll_mode_disable(cur);
02415         if ((cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) == 0) {
02416             tr_debug("PULL kEY Done by Host");
02417             cur->nwk_bootstrap_state = ER_BOOTSRAP_DONE;
02418             nwk_6lowpan_bootstrap_ready(cur);
02419         } else {
02420             tr_debug("PULL kEY Done by Router");
02421 #ifdef PANA
02422             cur->nwk_bootstrap_state = ER_PANA_PING;
02423             nwk_6lowpan_pana_key_pull(cur);
02424 #endif
02425         }
02426 
02427         nwk_protocol_network_key_set_from_pana(cur);
02428 #ifndef NO_TLS
02429 #endif
02430 
02431     }
02432 }
02433 
02434 
02435 bool protocol_6lowpan_bootsrap_link_set(protocol_interface_info_entry_t *interface, mlme_pan_descriptor_t *pan_descriptor, const uint8_t *beacon_payload, uint8_t beacon_length)
02436 {
02437     mlme_start_t start_req;
02438     memset(&start_req, 0, sizeof(mlme_start_t));
02439     mac_helper_coordinator_address_set(interface, (addrtype_t)pan_descriptor->CoordAddrMode, pan_descriptor->CoordAddress);
02440 
02441     interface->mac_parameters->mac_channel = pan_descriptor->LogicalChannel;
02442     interface->mac_parameters->pan_id = pan_descriptor->CoordPANId;
02443     if (interface->nwk_wpan_nvm_api) {
02444         wpan_nvm_params_t *params = interface->nwk_wpan_nvm_api->nvm_params_get_cb(interface->nwk_wpan_nvm_api, pan_descriptor->CoordPANId);
02445         interface->if_lowpan_security_params->mle_security_frame_counter = params->mle_securit_counter;
02446         //SET MAC and MLE security frame counters
02447         mle_service_security_set_frame_counter(interface->id, params->mle_securit_counter);
02448         mac_helper_link_frame_counter_set(interface->id, params->mac_security_frame_counter);
02449     }
02450 
02451     start_req.PANId = pan_descriptor->CoordPANId;
02452     start_req.LogicalChannel = pan_descriptor->LogicalChannel;
02453     start_req.ChannelPage = 0;
02454     start_req.BeaconOrder = pan_descriptor->SuperframeSpec[0] >> 4;
02455     start_req.SuperframeOrder = pan_descriptor->SuperframeSpec[0] & 0x0f;
02456     //SET Beacon Payload
02457     uint8_t *b_ptr = mac_helper_beacon_payload_reallocate(interface, beacon_length);
02458     if (!b_ptr) {
02459         tr_error("Beacon Payload allocate Fail");
02460         bootsrap_next_state_kick(ER_BOOTSTRAP_SCAN_FAIL, interface);
02461         return false;
02462     }
02463     memcpy(b_ptr, beacon_payload, beacon_length);
02464     mac_helper_beacon_payload_register(interface);
02465     //Start and set pan-id
02466     interface->mac_api->mlme_req(interface->mac_api, MLME_START, &start_req);
02467     mac_helper_panid_set(interface, pan_descriptor->CoordPANId);
02468 
02469     return true;
02470 }
02471 
02472 bool protocol_6lowpan_bootsrap_start(protocol_interface_info_entry_t *interface)
02473 {
02474     net_load_balance_internal_state_activate(interface, false);
02475 
02476     //SET allways RX ON Idle device by default
02477     mac_helper_pib_boolean_set(interface, macRxOnWhenIdle, true);
02478     interface->lowpan_info &=  ~INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE;
02479 
02480     mac_data_poll_init(interface);
02481     mac_helper_mac16_address_set(interface, 0xffff);
02482     tr_debug("Mac Ready");
02483     interface->nwk_nd_re_scan_count = 2;
02484 
02485     if (interface->if_lowpan_security_params->nwk_security_mode == NET_SEC_MODE_PSK_LINK_SECURITY) {
02486         tr_debug("SET Security Mode");
02487         mac_helper_default_security_level_set(interface, interface->mac_parameters->mac_configured_sec_level);
02488         mac_helper_default_security_key_id_mode_set(interface, MAC_KEY_ID_MODE_IDX);
02489     }
02490 
02491     //Check first pana and then MLE and else start RS scan pahse
02492     if (interface->lowpan_info & INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION) {
02493 #ifdef PANA
02494         nwk_6lowpan_bootsrap_pana_authentication_start(interface);
02495         tr_debug("Pana auth");
02496 #else
02497         bootsrap_next_state_kick(ER_BOOTSTRAP_SCAN_FAIL, interface);
02498         return false;
02499 #endif
02500     } else if (interface->lowpan_info & INTERFACE_NWK_BOOTSRAP_MLE) {
02501         if (protocol_6lowpan_parent_link_req(interface) != 0) {
02502             bootsrap_next_state_kick(ER_BOOTSTRAP_SCAN_FAIL, interface);
02503             return false;
02504         }
02505     } else {
02506         bootsrap_next_state_kick(ER_SCAN, interface);
02507     }
02508     return true;
02509 }
02510 
02511 
02512 void protocol_6lowpan_mac_scan_confirm(int8_t if_id, const mlme_scan_conf_t *conf)
02513 {
02514     nwk_pan_descriptor_t *result;
02515     nwk_pan_descriptor_t *best;
02516     protocol_interface_info_entry_t *interface = NULL;
02517 
02518     if (conf->ScanType != MAC_ACTIVE_SCAN) {
02519         return;
02520     }
02521 
02522     interface = protocol_stack_interface_info_get_by_id(if_id);
02523     if (!interface) {
02524         tr_debug("Mac scan confirm:Unknow Interface");
02525         return;
02526     }
02527     bool is_border_router = false;
02528     if (interface->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
02529         is_border_router = true;
02530     }
02531 
02532     interface->mac_parameters->nwk_scan_params.active_scan_active = false;
02533 
02534     result = arm_net_get_scanned_nwk_list(if_id);
02535     if (!result || !conf->ResultListSize) {
02536         tr_debug("Mac scan confirm:No Beacons");
02537         if (is_border_router == false) {
02538             bootsrap_next_state_kick(ER_BOOTSTRAP_SCAN_FAIL, interface);
02539             return;
02540         }
02541     }
02542 
02543     //Analyze Best Result
02544     best = mac_helper_select_best_lqi(result);
02545     mac_helper_drop_selected_from_the_scanresult(&interface->mac_parameters->nwk_scan_params, best);
02546 
02547     bool link_start_ok = false;
02548     if (is_border_router == false) {
02549         link_start_ok = protocol_6lowpan_bootsrap_link_set(interface, best->pan_descriptor, best->beacon_payload, best->beacon_length);
02550     }
02551 
02552     mac_helper_free_scan_confirm(&interface->mac_parameters->nwk_scan_params);
02553 
02554     best = mac_helper_free_pan_descriptions(best);
02555 
02556     if (link_start_ok) {
02557         protocol_6lowpan_bootsrap_start(interface);
02558     }
02559 
02560     if (is_border_router == true) {
02561         if (interface->nwk_bootstrap_state == ER_WARM_ACTIVE_SCAN) {
02562             border_router_start(interface, true);
02563             interface->bootsrap_state_machine_cnt = 0;
02564             interface->nwk_bootstrap_state = ER_BOOTSRAP_DONE;
02565         } else {
02566             border_router_start(interface, false);
02567         }
02568 
02569     }
02570 }
02571 
02572 void bootstrap_timer_handle(uint16_t ticks)
02573 {
02574     (void)ticks;
02575     ns_list_foreach(protocol_interface_info_entry_t, cur, &protocol_interface_info_list) {
02576         if (cur->nwk_id == IF_6LoWPAN) {
02577             if (cur->nwk_bootstrap_state == ER_ACTIVE_SCAN || cur->nwk_bootstrap_state == ER_WARM_ACTIVE_SCAN) {
02578                 // Retransmit Scan request
02579                 bootsrap_next_state_kick(cur->nwk_bootstrap_state, cur);
02580                 tr_error("Restart active scan");
02581             } else {
02582                 // Retransmit Start request
02583                 mlme_start_t start_req;
02584                 memset(&start_req, 0, sizeof(mlme_start_t));
02585                 start_req.PANId = cur->border_router_setup->mac_panid;
02586                 start_req.LogicalChannel = cur->mac_parameters->mac_channel;
02587                 start_req.ChannelPage = 0;
02588                 start_req.BeaconOrder = 0x0f;
02589                 start_req.SuperframeOrder = 0x0f;
02590                 start_req.PANCoordinator = 1;
02591                 if (cur->mac_api) {
02592                     cur->mac_api->mlme_req(cur->mac_api, MLME_START, (void *)&start_req);
02593                     tr_error("Restart MAC");
02594                 }
02595             }
02596         }
02597     }
02598 }
02599 
02600 void protocol_6lowpan_bootstrap(protocol_interface_info_entry_t *cur)
02601 {
02602     switch (cur->nwk_bootstrap_state) {
02603         case ER_ACTIVE_SCAN:
02604         case ER_WARM_ACTIVE_SCAN:
02605             tr_debug("Start Active Scan");
02606             cur->mac_parameters->nwk_scan_params.stack_chan_list = cur->mac_parameters->mac_channel_list;
02607 
02608             mlme_scan_t req;
02609             mac_create_scan_request(MAC_ACTIVE_SCAN, &cur->mac_parameters->mac_channel_list, cur->mac_parameters->nwk_scan_params.scan_duration, &req);
02610             if (cur->mac_api) {
02611                 cur->scan_cb = protocol_6lowpan_mac_scan_confirm;
02612                 cur->mac_parameters->nwk_scan_params.active_scan_active = true;
02613                 if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
02614                     protocol_timer_start(PROTOCOL_TIMER_BOOTSTRAP_TIM, bootstrap_timer_handle, BOOTSTRAP_SCAN_TIMEOUT);
02615                 }
02616                 cur->mac_api->mlme_req(cur->mac_api, MLME_SCAN, &req);
02617             }
02618             break;
02619 
02620         case ER_SCAN:
02621             //LED1_TOGGLE();
02622             nwk_6lowpan_router_scan_state(cur);
02623             break;
02624 
02625         case ER_PANA_AUTH_ERROR:
02626             nwk_6lowpan_network_authentication_fail(cur);
02627             break;
02628 
02629         case ER_PANA_AUTH_DONE:
02630             nwk_6lowpan_network_authentication_done(cur);
02631             break;
02632 
02633         case ER_BIND_COMP:
02634             nwk_6lowpan_nd_address_registartion_ready(cur);
02635             break;
02636 
02637 #ifdef HAVE_RPL
02638 
02639         case ER_RPL_MC:
02640             nwk_6lowpan_rpl_router_discover(cur);
02641             break;
02642 
02643         case ER_RPL_SCAN:
02644             nwk_6lowpan_rpl_router_result_check(cur);
02645             break;
02646 #endif
02647         case ER_BOOTSRAP_DONE:
02648             nwk_6lowpan_bootstrap_ready(cur);
02649             break;
02650 
02651         case ER_PARENT_SYNCH_LOST:
02652             tr_debug("-->Parent synch Lose");
02653             nwk_bootsrap_state_update(ARM_NWK_NWK_PARENT_POLL_FAIL, cur);
02654             break;
02655 
02656         case ER_BOOTSTRAP_CONNECTION_DOWN:
02657             nwk_bootsrap_state_update(ARM_NWK_NWK_CONNECTION_DOWN, cur);
02658             break;
02659 
02660         case ER_BOOTSTRAP_IP_ADDRESS_ALLOC_FAIL:
02661             nwk_bootsrap_state_update(ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL, cur);
02662             tr_info("-->idle");
02663             break;
02664 
02665         case ER_BOOTSTRAP_DAD_FAIL:
02666             nwk_bootsrap_state_update(ARM_NWK_DUPLICATE_ADDRESS_DETECTED, cur);
02667             break;
02668 
02669         case ER_BOOTSTRAP_SCAN_FAIL:
02670             tr_debug("Network Bootsrap Start Fail");
02671             nwk_bootsrap_state_update(ARM_NWK_NWK_SCAN_FAIL, cur);
02672             break;
02673 #ifdef PANA
02674         case ER_PANA_PING:
02675             nwk_6lowpan_pana_key_pull(cur);
02676             break;
02677 #endif
02678         case ER_MLE_LINK_REQ:
02679             //No need to do anything in this case
02680             break;
02681         default:
02682             tr_error("Unknow state %d", cur->nwk_bootstrap_state);
02683 
02684     }
02685 }
02686 
02687 void protocol_6lowpan_nd_borderrouter_connection_down(protocol_interface_info_entry_t *interface)
02688 {
02689     /*if (rpl_object_poisons() == 0) ??? */ {
02690         mac_helper_mac16_address_set(interface, 0xffff);
02691 
02692         //TRIG Event for ND connection Down
02693         bootsrap_next_state_kick(ER_BOOTSTRAP_IP_ADDRESS_ALLOC_FAIL, interface);
02694     }
02695 }
02696 
02697 void protocol_6lowpan_bootstrap_re_start(protocol_interface_info_entry_t *interface)
02698 {
02699     mac_helper_mac16_address_set(interface, 0xffff);
02700     arm_6lowpan_bootstrap_init(interface);
02701     tr_info("-->Bootsrap");
02702 }
02703 
02704 uint8_t *protocol_6lowpan_nd_border_router_address_get(nwk_interface_id nwk_id)
02705 {
02706     nd_router_t   *object = nd_get_object_by_nwk_id(nwk_id);
02707     if (object) {
02708         return object->border_router;
02709     }
02710     return 0;
02711 }
02712 
02713 uint8_t protocol_6lowpan_rf_link_scalability_from_lqi(uint8_t lqi)
02714 {
02715     uint8_t i = 16;
02716     if (lqi >= 240) {
02717         i = 1;
02718     } else {
02719         lqi /= 16;
02720         if (lqi) {
02721             i = (16 - lqi);
02722         }
02723     }
02724     return i;
02725 }
02726 
02727 int protocol_6lowpan_del_ll16(protocol_interface_info_entry_t *cur, uint16_t mac_short_address)
02728 {
02729     uint8_t address[16];
02730     memcpy(address, ADDR_LINK_LOCAL_PREFIX, 8);
02731     memcpy(address + 8, ADDR_SHORT_ADR_SUFFIC, 6);
02732     common_write_16_bit(mac_short_address, &address[14]);
02733 
02734     return addr_delete(cur, address);
02735 }
02736 
02737 int protocol_6lowpan_set_ll16(protocol_interface_info_entry_t *cur, uint16_t mac_short_address)
02738 {
02739     if_address_entry_t *address_entry;
02740     uint8_t address[16];
02741     memcpy(address, ADDR_LINK_LOCAL_PREFIX, 8);
02742     memcpy(address + 8, ADDR_SHORT_ADR_SUFFIC, 6);
02743     common_write_16_bit(mac_short_address, &address[14]);
02744 
02745     address_entry = addr_add(cur, address, 64, ADDR_SOURCE_UNKNOWN, 0xffffffff, 0xffffffff, false);
02746     if (address_entry) {
02747         return 0;
02748     }
02749     return -1;
02750 }
02751 
02752 static void protocol_6lowpan_generate_link_reject(protocol_interface_info_entry_t *cur, const mlme_comm_status_t *status)
02753 {
02754     uint8_t address[16];
02755     memcpy(address, ADDR_LINK_LOCAL_PREFIX, 8);
02756     if (status->SrcAddrMode == MAC_ADDR_MODE_16_BIT) {
02757         memcpy(address + 8, ADDR_SHORT_ADR_SUFFIC, 6);
02758         memcpy(address + 14, status->SrcAddr, 2);
02759     } else {
02760         memcpy(address + 8, status->SrcAddr, 8);
02761         address[8] ^= 2;
02762     }
02763     if (mac_helper_default_security_level_get(cur)) {
02764         tr_debug("Drop link by asymmetric security");
02765         mle_service_reject_message_build(cur->id, address, false);
02766         return;
02767     }
02768 
02769 }
02770 
02771 static void lowpan_comm_status_indication_cb(int8_t if_id, const mlme_comm_status_t *status)
02772 {
02773     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(if_id);
02774     if (!cur) {
02775         return;
02776     }
02777 
02778     mac_neighbor_table_entry_t *entry_ptr;
02779 
02780     switch (status->status) {
02781         case MLME_UNSUPPORTED_SECURITY:
02782         case MLME_UNAVAILABLE_KEY:
02783             /* Generate MLE Link Reject to destination */
02784             if (status->DstAddrMode == MAC_ADDR_MODE_16_BIT && status->DstAddr[0] == 0xff && status->DstAddr[1] == 0xff) {
02785                 return; //Drop brodcast security failure
02786             }
02787 
02788             if (!cur->mle_link_reject_tokens) {
02789                 return;
02790             }
02791             cur->mle_link_reject_tokens--;
02792             protocol_6lowpan_generate_link_reject(cur, status);
02793 
02794             break;
02795         case MLME_DATA_POLL_NOTIFICATION:
02796             entry_ptr = mac_neighbor_table_address_discover(mac_neighbor_info(cur), status->SrcAddr, status->SrcAddrMode);
02797             if (entry_ptr) {
02798                 // Refresh Timeout
02799                 mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_ptr, entry_ptr->link_lifetime );
02800             }
02801             break;
02802         default:
02803             break;
02804     }
02805 }
02806 
02807 bool lowpan_neighbour_data_clean(int8_t interface_id, const uint8_t *link_local_address)
02808 {
02809 
02810     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
02811     if (!cur) {
02812         return false;
02813     }
02814     bool return_value = false;
02815     mac_neighbor_table_entry_t *neigh_entry = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), link_local_address, false, NULL);
02816     if (neigh_entry) {
02817         //Remove entry
02818         if (neigh_entry->link_role  == PRIORITY_PARENT_NEIGHBOUR || neigh_entry->link_role  == SECONDARY_PARENT_NEIGHBOUR) {
02819             return_value = true;
02820         }
02821         mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), neigh_entry);
02822     }
02823     return return_value;
02824 }
02825 
02826 void protocol_6lowpan_mle_timer(uint16_t ticks_update)
02827 {
02828 #ifndef NO_MLE
02829     if (mle_6lowpan_data) {
02830         /* Three request in burst and after that one link request per second */
02831         mle_6lowpan_data->link_req_token_bucket += ticks_update;
02832         if (mle_6lowpan_data->link_req_token_bucket > MLE_LINK_REQ_TOKEN_BUCKET_SIZE) {
02833             mle_6lowpan_data->link_req_token_bucket = MLE_LINK_REQ_TOKEN_BUCKET_SIZE;
02834         }
02835     }
02836 #endif
02837 }
02838 
02839 #endif