takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

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-2018, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 /*
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     uint8_t advert_neigh_cnt;
00328     uint8_t neighb_max;
00329 
00330     uint8_t mle_neigh_cnt = mle_class_active_neigh_counter(cur_interface);
00331 
00332     if (short_adr == true) {
00333         neighb_max = 16;
00334     } else {
00335         neighb_max = 5;
00336     }
00337 
00338     if (mle_neigh_cnt > neighb_max) {
00339         advert_neigh_cnt = neighb_max;
00340     } else {
00341         advert_neigh_cnt = mle_neigh_cnt;
00342     }
00343 
00344     return (advert_neigh_cnt);
00345 }
00346 
00347 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)
00348 {
00349     uint8_t entry_size;
00350 
00351     if (data_length) {
00352         entry_size = (*ptr++ & 0x0f) + 3;
00353         data_length--;
00354 
00355         // Supports 2 and 8 bytes long MAC addresses
00356         if ((entry_size == 4) || (entry_size == 10)) {
00357 
00358             uint8_t own_addr_match = false;
00359 
00360             // Searches own address from link quality TLV
00361             while (data_length >= entry_size ) {
00362 
00363                 if (entry_size == 4){
00364                     if (common_read_16_bit(ptr + 2) == short_address) {
00365                         own_addr_match = true;
00366                     }
00367                 } else {
00368                     if (memcmp(ptr + 2, mac64, 8) == 0) {
00369                         own_addr_match = true;
00370                     }
00371                 }
00372 
00373                 // If own address is found returns success
00374                 if (own_addr_match) {
00375                     if (iop_flags_ptr) {
00376                         *iop_flags_ptr = ptr[0];
00377                     }
00378                     if (link_idr_ptr) {
00379                         *link_idr_ptr = ptr[1];
00380                     }
00381                     return 1;
00382                 }
00383 
00384                 ptr += entry_size;
00385                 data_length -= entry_size;
00386             }
00387         }
00388     }
00389     return 0;
00390 }
00391 
00392 static bool neighbor_list_short_address_available(mac_neighbor_table_t *table_class)
00393 {
00394     ns_list_foreach(mac_neighbor_table_entry_t, cur_entry, &table_class->neighbour_list ) {
00395         if (cur_entry->connected_device && cur_entry->mac16 == 0xffff) {
00396             return false;
00397         }
00398     }
00399     return true;
00400 }
00401 
00402 
00403 static uint8_t *mle_table_set_neighbours(protocol_interface_info_entry_t *cur, uint8_t *ptr)
00404 {
00405     uint8_t *len_ptr = 0;
00406     uint8_t neigh_count = 0;
00407     uint8_t neigh_count_max = 0;
00408     uint8_t *link_flags_ptr;
00409     mac_neighbor_table_entry_t *first_entry_ptr = NULL;
00410 
00411     mac_neighbor_table_list_t * neigh_list = &cur->mac_parameters->mac_neighbor_table->neighbour_list;
00412 
00413     *ptr++ = MLE_TYPE_LINK_QUALITY;
00414     len_ptr = ptr++;
00415     *len_ptr = 1;
00416 
00417     link_flags_ptr = ptr++;
00418     //*link_flags_ptr = 0x81;
00419     bool use_short_address_compression = neighbor_list_short_address_available(mac_neighbor_info(cur));
00420     if (use_short_address_compression) {
00421         //complete, 2 bytes long link-layer address
00422         *link_flags_ptr = 0x81;
00423     } else {
00424         //complete, 8 bytes long link-layer address
00425         *link_flags_ptr = 0x87;
00426 
00427     }
00428     neigh_count_max = mle_advert_neigh_cnt(cur, use_short_address_compression);
00429 
00430     bool clean_entries = false;
00431     ns_list_foreach(mac_neighbor_table_entry_t, cur_entry, neigh_list)
00432     {
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                         {
01184                             drop_advertisment = 0;
01185                         }
01186 
01187                         if (drop_advertisment) {
01188                             if (link_flags & 0x80) {
01189                                 //Total Entry at messgae
01190                                 //Possible remove
01191                                 if ((mode & MLE_DEV_MASK) == MLE_RFD_DEV) {
01192                                     //Remove Entry
01193                                     mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), entry_temp);
01194                                     tr_error("MLE adv: Own address not found");
01195                                     return;
01196                                 }
01197                             }
01198                         }
01199                     }
01200                 }
01201 
01202                 //UPDATE
01203                 mle_neigh_entry_update_by_mle_tlv_list(cur->id,entry_temp, mle_msg->data_ptr, mle_msg->data_length, cur->mac, own_mac16);
01204                 mle_neigh_entry_frame_counter_update(entry_temp, mle_msg->data_ptr, mle_msg->data_length, cur, security_headers->KeyIndex);
01205                 if (entry_temp->connected_device ) {
01206                     mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, entry_temp->link_lifetime );
01207                 }
01208             }
01209             break;
01210 
01211         default:
01212             break;
01213     }
01214 }
01215 
01216 int8_t arm_6lowpan_mle_service_ready_for_security_init(protocol_interface_info_entry_t *cur)
01217 {
01218     //Verify MLE Service
01219     if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_MLE) {
01220         //validate MLE service
01221         if (!mle_service_interface_registeration_validate(cur->id)) {
01222             //Register
01223             if (mle_service_interface_register(cur->id,cur, mle_6lowpan_message_handler, cur->mac,8) != 0) {
01224                 tr_error("Mle Service init Fail");
01225                 return -1;
01226             }
01227             if (mle_6lowpan_data) {
01228                 if (mle_service_interface_token_bucket_settings_set(cur->id, mle_6lowpan_data->token_bucket_size,
01229                     mle_6lowpan_data->token_bucket_rate, mle_6lowpan_data->token_bucket_count) < 0) {
01230                     return -1;
01231                 }
01232                 mle_service_set_frame_counter_check(true);
01233                 mle_service_set_accept_invalid_frame_counter(true);
01234             }
01235         }
01236     }
01237     return 0;
01238 }
01239 
01240 static uint8_t protocol_6lowpan_mle_data_allocate(void)
01241 {
01242     if (mle_6lowpan_data) {
01243         return 0;
01244     }
01245 
01246     mle_6lowpan_data = ns_dyn_mem_alloc(sizeof(mle_6lowpan_data_t));
01247 
01248     if (!mle_6lowpan_data) {
01249         return 0;
01250     }
01251 
01252     mle_6lowpan_data->router_lifetime = MLE_ROUTER_DEFAULT_LIFETIME;
01253     mle_6lowpan_data->host_lifetime = MLE_ROUTER_HOST_LIFETIME;
01254     mle_6lowpan_data->nbr_of_neigh_lower_threshold = MLE_NBR_OF_NEIGHBOR_MAX_LIMIT;
01255     mle_6lowpan_data->nbr_of_neigh_upper_threshold = MLE_NBR_OF_NEIGHBOR_LOWER_THRESHOLD;
01256     mle_6lowpan_data->nbr_of_neigh_max = MLE_NBR_OF_NEIGHBOR_UPPER_THRESHOLD;
01257 
01258     mle_6lowpan_data->token_bucket_size = MLE_TOKEN_BUCKET_SIZE;
01259     mle_6lowpan_data->token_bucket_rate = MLE_TOKEN_BUCKET_RATE;
01260     mle_6lowpan_data->token_bucket_count = MLE_TOKEN_BUCKET_COUNT;
01261 
01262     mle_6lowpan_data->link_req_token_bucket = MLE_LINK_REQ_TOKEN_BUCKET_SIZE;
01263 
01264     return 0;
01265 }
01266 
01267 mle_6lowpan_data_t *protocol_6lowpan_mle_data_get(void)
01268 {
01269     return mle_6lowpan_data;
01270 }
01271 
01272 static void protocol_6lowpan_mle_purge_neighbors(struct protocol_interface_info_entry *cur_interface, uint8_t entry_count, uint8_t force_priority)
01273 {
01274 
01275     uint8_t count = 0;
01276     uint8_t ll64[16];
01277 
01278     if (!cur_interface) {
01279         return;
01280     }
01281     mac_neighbor_table_list_t *mac_table_list = &cur_interface->mac_parameters->mac_neighbor_table->neighbour_list;
01282 
01283     entry_count = protocol_6lowpan_mle_order_last_entries(cur_interface->id, mac_table_list, entry_count);
01284 
01285     ns_list_foreach_reverse_safe(mac_neighbor_table_entry_t, entry, mac_table_list) {
01286         if (++count > entry_count) {
01287             break;
01288         }
01289 
01290         if (!force_priority) {
01291             if (entry->link_role ==  PRIORITY_PARENT_NEIGHBOUR || entry->link_role == CHILD_NEIGHBOUR) {
01292                 break;
01293             }
01294         }
01295 
01296         memcpy(ll64, ADDR_LINK_LOCAL_PREFIX, 8);
01297         memcpy(&ll64[8], entry->mac64, 8);
01298         ll64[8] ^= 2;
01299 
01300         tr_debug("MLE purge");
01301 
01302         // Sends REJECT
01303         mle_service_reject_message_build(cur_interface->id, ll64, false);
01304         mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur_interface), entry);
01305 
01306         // Adds purged neighbor to blacklist so that it is not added right away back from advertisement
01307         blacklist_update(ll64, false);
01308     }
01309 }
01310 
01311 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)
01312 {
01313     mac_neighbor_table_entry_t *last;
01314     mac_neighbor_table_entry_t *first_ordered = NULL;
01315     etx_storage_t * etx_last, *etx_cur;
01316     uint8_t count = 0;
01317     do {
01318         last = NULL;
01319 
01320         ns_list_foreach(mac_neighbor_table_entry_t, entry, mac_neigh_table) {
01321 
01322             if (entry == first_ordered) {
01323                 break;
01324             }
01325 
01326             if (last == NULL) {
01327                 last = entry;
01328                 continue;
01329             }
01330 
01331             if (entry->link_role > last->link_role ) { //Bigger link role is allways better
01332                 continue;
01333             } else if (entry->link_role == last->link_role ) {
01334                 // Compare ETX when Link role is same
01335                 etx_cur = etx_storage_entry_get(interface_id, entry->index);
01336                 etx_last = etx_storage_entry_get(interface_id, last->index );
01337                 if (etx_cur && etx_last && etx_cur->etx <= etx_last->etx) {
01338                     continue;
01339                 }
01340             }
01341             last = entry;
01342         }
01343 
01344         // Sets last to end of list
01345         if (last) {
01346             ns_list_remove(mac_neigh_table, last);
01347 
01348             if (first_ordered) {
01349                 ns_list_add_before(mac_neigh_table, first_ordered, last);
01350             } else {
01351                 ns_list_add_to_end(mac_neigh_table, last);
01352             }
01353 
01354             first_ordered = last;
01355 
01356             count++;
01357 
01358             if (count == entry_count) {
01359                 break;
01360             }
01361         // If no lasts anymore then exits
01362         } else {
01363             break;
01364         }
01365 
01366     } while (true);
01367 
01368     return count;
01369 }
01370 
01371 static int8_t arm_6lowpan_bootstrap_down(protocol_interface_info_entry_t *cur)
01372 {
01373     if (!cur || !(cur->lowpan_info & INTERFACE_NWK_ACTIVE)) {
01374         return -1;
01375     }
01376     mac_data_poll_disable(cur);
01377     /* Save security counter values to RAM and NVM */
01378     if (cur->nwk_wpan_nvm_api) {
01379         cur->nwk_wpan_nvm_api->nvm_params_update_cb(cur->nwk_wpan_nvm_api, true);
01380     }
01381     cur->if_lowpan_security_params->mle_security_frame_counter = mle_service_security_get_frame_counter(cur->id);
01382     mle_service_interface_receiver_handler_update(cur->id, mle_6lowpan_message_handler);
01383     return nwk_6lowpan_down(cur);
01384 }
01385 #ifdef HAVE_6LOWPAN_ND
01386 
01387 static void lowpan_mle_receive_security_bypass_cb(int8_t interface_id, mle_message_t *mle_msg)
01388 {
01389     (void) interface_id;
01390 #ifdef PANA
01391     protocol_interface_info_entry_t *interface = mle_msg->interface_ptr;
01392     //Accept Only Link Reject
01393     if (mle_msg->message_type == MLE_COMMAND_REJECT) {
01394 
01395         if ((interface->lowpan_info & (INTERFACE_NWK_BOOTSRAP_ACTIVE | INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION)) != (INTERFACE_NWK_BOOTSRAP_ACTIVE | INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION)) {
01396                 return;
01397             }
01398 
01399             if (protocol_6lowpan_interface_compare_cordinator_netid(interface, mle_msg->packet_src_address + 8) != 0) {
01400                 return;
01401             }
01402 
01403             if (interface->nwk_bootstrap_state != ER_PANA_AUTH) {
01404                 return;
01405             }
01406 
01407             //Stop Pana and call ECC
01408             tr_debug("MLE Link reject from cordinator");
01409             pana_reset_client_session();
01410             bootsrap_next_state_kick(ER_PANA_AUTH_ERROR, interface);
01411     }
01412 #endif
01413 }
01414 
01415 void arm_6lowpan_security_init_ifup(protocol_interface_info_entry_t *cur)
01416 {
01417     if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_MLE) {
01418 
01419         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);
01420         switch (cur->if_lowpan_security_params->nwk_security_mode) {
01421 
01422             case NET_SEC_MODE_PSK_LINK_SECURITY:
01423 
01424             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);
01425             mle_service_security_set_frame_counter(cur->id, cur->if_lowpan_security_params->mle_security_frame_counter);
01426             break;
01427             case NET_SEC_MODE_PANA_LINK_SECURITY:
01428                 mle_service_interface_receiver_bypass_handler_update(cur->id, lowpan_mle_receive_security_bypass_cb);
01429                 break;
01430             default:
01431                 break;
01432         }
01433     }
01434 
01435     cur->mac_parameters->mac_key_id_mode = MAC_KEY_ID_MODE_IDX;
01436     cur->mac_parameters->mac_configured_sec_level = cur->if_lowpan_security_params->security_level;
01437     switch (cur->if_lowpan_security_params->nwk_security_mode) {
01438 
01439         case NET_SEC_MODE_PANA_LINK_SECURITY:
01440             cur->lowpan_info |= (INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION);
01441             break;
01442 
01443         case NET_SEC_MODE_PSK_LINK_SECURITY:
01444             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);
01445             /* fall through */
01446         default:
01447             cur->lowpan_info &= ~INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION;
01448             break;
01449     }
01450 }
01451 #endif
01452 
01453 static int8_t arm_6lowpan_bootstrap_up(protocol_interface_info_entry_t *cur)
01454 {
01455     int8_t ret_val = -1;
01456     if ((cur->configure_flags & INTERFACE_SETUP_MASK) != INTERFACE_SETUP_READY) {
01457         tr_debug("Interface not yet fully configured");
01458         ret_val = -5;
01459     } else {
01460 
01461         //Verify MLE Service
01462         if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_MLE) {
01463             //validate MLE service
01464             if (!mle_service_interface_registeration_validate(cur->id)) {
01465                 //Register
01466 
01467                 if (mle_service_interface_register(cur->id, cur, mle_6lowpan_message_handler, cur->mac,8) != 0) {
01468                     tr_error("Mle Service init Fail");
01469                     return -1;
01470                 }
01471             }
01472 
01473             if (mle_6lowpan_data) {
01474                 if (mle_service_interface_token_bucket_settings_set(cur->id, mle_6lowpan_data->token_bucket_size,
01475                                                                     mle_6lowpan_data->token_bucket_rate, mle_6lowpan_data->token_bucket_count) < 0) {
01476                     tr_error("Mle Service tokens set Fail");
01477                     return -1;
01478                 }
01479                 mle_service_set_frame_counter_check(true);
01480                 mle_service_set_accept_invalid_frame_counter(true);
01481             }
01482         }
01483 
01484         arm_6lowpan_security_init_ifup(cur);
01485 
01486         //SET 6lowpan default here
01487         mac_helper_mac_mlme_max_retry_set(cur->id, LOWPAN_MAX_FRAME_RETRIES);
01488 
01489         addr_interface_set_ll64(cur, NULL);
01490         if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_ROUTER) {
01491             cur->lowpan_info |= INTERFACE_NWK_ROUTER_DEVICE;
01492             //rpl_control_set_domain_on_interface(cur, protocol_6lowpan_rpl_domain, true);
01493             icmpv6_radv_enable(cur);
01494         }
01495         ret_val = nwk_6lowpan_up(cur);
01496     }
01497     return ret_val;
01498 }
01499 #endif
01500 
01501 void arm_6lowpan_bootstrap_init(protocol_interface_info_entry_t *cur)
01502 {
01503     //Init 6lowpan Bootsrap
01504     icmp_nd_routers_init();
01505     cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ACTIVE;
01506     cur->lowpan_info &= ~INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY;
01507     bootsrap_next_state_kick(ER_SCAN, cur);
01508     mac_helper_mac16_address_set(cur, 0xffff);
01509 }
01510 
01511 #ifdef HAVE_6LOWPAN_ND
01512 static void arm_6lowpan_bootstrap_functions_set(protocol_interface_info_entry_t *cur)
01513 {
01514     cur->if_up = arm_6lowpan_bootstrap_up;
01515     cur->if_down = arm_6lowpan_bootstrap_down;
01516 }
01517 
01518 static uint8_t protocol_6lowpan_analyze_beacon_payload(uint8_t *ptr, uint8_t len, protocol_interface_info_entry_t *cur)
01519 {
01520     (void)len;
01521     nwk_filter_params_s *filter = &(cur->mac_parameters->nwk_filter_params);
01522 
01523     if (*ptr == filter->beacon_protocol_id_filter || filter->beacon_protocol_id_filter == 0xff) {
01524         ptr++;
01525         if (filter->nwk_active_scan_level == 2) {
01526             if ((*ptr & 1)) {
01527                 if (filter->beacon_nwk_id_filter) {
01528                     ptr++;
01529                     if (memcmp(filter->beacon_nwk_id_filter, ptr, 16)) {
01530                         tr_debug("NWK ID filter");
01531                         return 0;
01532                     }
01533                 }
01534                 return 1;
01535             }
01536         } else {
01537             return 1;
01538         }
01539     }
01540 
01541     return 0;
01542 }
01543 
01544 int8_t arm_network_processor_up(protocol_interface_info_entry_t *cur)
01545 {
01546     int8_t ret_val = -1;
01547     if ((cur->configure_flags & INTERFACE_SETUP_NETWORK_DRIVER_MASK) != INTERFACE_SETUP_NETWORK_DRIVER_READY) {
01548         tr_debug("Interface not yet fully configured\n");
01549         ret_val = -5;
01550     } else {
01551         protocol_6lowpan_register_handlers(cur);
01552         mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, true);
01553         mac_helper_default_security_level_set(cur, SEC_NONE);
01554 
01555         if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_RF_SNIFFER) {
01556             mac_helper_pib_boolean_set(cur, macAssociationPermit, false);
01557             mac_helper_pib_boolean_set(cur, macPromiscuousMode, true);
01558             lowpan_bootstrap_pan_control(cur, false);
01559 
01560         } else if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_RF_ACCESPOINT) {
01561             // Updates beacon
01562             beacon_join_priority_update(cur->id);
01563             mac_helper_pib_boolean_set(cur, macAssociationPermit, true);
01564             net_load_balance_internal_state_activate(cur, true);
01565         }
01566 
01567         cur->nwk_bootstrap_state = ER_BOOTSRAP_DONE;
01568         cur->interface_mode = INTERFACE_UP;
01569         cur->nwk_mode = ARM_NWK_RAW_PHY_MODE;
01570         cur->lowpan_info |= (INTERFACE_NWK_ACTIVE | INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY);
01571         cur->bootsrap_state_machine_cnt = 0;
01572         nwk_bootsrap_state_update(ARM_NWK_BOOTSTRAP_READY, cur);
01573 
01574         ret_val = 0;
01575     }
01576     return ret_val;
01577 }
01578 
01579 static void arm_6lowpan_security_key_update_cb(protocol_interface_info_entry_t *cur, const mlme_security_t *security_params)
01580 {
01581     if (cur->mac_parameters->mac_next_key_index && (security_params->KeyIndex == cur->mac_parameters->mac_next_key_index)) {
01582         tr_debug("Trig Next Key");
01583         mac_helper_security_key_swap_next_to_default(cur);
01584         mle_service_security_key_trig(cur->id, security_params->KeyIndex);
01585         if (cur->nwk_wpan_nvm_api) {
01586             cur->nwk_wpan_nvm_api->nvm_params_update_cb(cur->nwk_wpan_nvm_api, true);
01587         }
01588     }
01589 }
01590 
01591 static void lowpan_neighbor_entry_remove_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data)
01592 {
01593 
01594     protocol_interface_info_entry_t *cur_interface = user_data;
01595     lowpan_adaptation_remove_free_indirect_table(cur_interface, entry_ptr);
01596     // Sleepy host
01597     if (cur_interface->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE) {
01598         mac_data_poll_protocol_poll_mode_decrement(cur_interface);
01599     }
01600 
01601     protocol_6lowpan_priority_neighbor_remove(cur_interface, entry_ptr);
01602 
01603     if (entry_ptr->ffd_device ) {
01604         protocol_6lowpan_release_short_link_address_from_neighcache(cur_interface, entry_ptr->mac16 );
01605         protocol_6lowpan_release_long_link_address_from_neighcache(cur_interface, entry_ptr->mac64 );
01606     }
01607     mac_helper_devicetable_remove(cur_interface->mac_api, entry_ptr->index );
01608     //Removes ETX neighbor
01609     etx_neighbor_remove(cur_interface->id, entry_ptr->index );
01610     //Remove MLE frame counter info
01611     mle_service_frame_counter_entry_delete(cur_interface->id, entry_ptr->index );
01612 
01613 }
01614 
01615 
01616 static bool lowpan_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data)
01617 {
01618 
01619     // Sleepy host
01620     protocol_interface_info_entry_t *cur_interface = user_data;
01621 
01622     if (cur_interface->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) {
01623         //Trig middle way challenge if Broadcast message  have been missed
01624         if (!entry_ptr->ffd_device ) {
01625             return false; //End device must do this
01626         }
01627 
01628         if (entry_ptr->lifetime  > (entry_ptr->link_lifetime  / 2)) {
01629             return false; //Trig only when midway is overed
01630         }
01631         return protocol_6lowpan_router_challenge(cur_interface, entry_ptr->mac64 );
01632     }
01633 
01634     if (entry_ptr->link_role  != PRIORITY_PARENT_NEIGHBOUR) {
01635         return false; //Do not never challenge than priority parent
01636     }
01637 
01638     if (cur_interface->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE) {
01639         return false; //Sleepy end device should not never challenge
01640     }
01641 
01642     if (entry_ptr->lifetime   > MLE_TABLE_CHALLENGE_TIMER) {
01643         return false;
01644     }
01645 
01646     return protocol_6lowpan_host_challenge(cur_interface, entry_ptr->mac64 );
01647 }
01648 
01649 
01650 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)
01651 {
01652     int8_t ret_val = -1;
01653     bool enable_mle_protocol = true;
01654     protocol_interface_info_entry_t *cur;
01655 
01656     cur = protocol_stack_interface_info_get_by_id(interface_id);
01657     if (!cur) {
01658         return -1;
01659     }
01660 
01661     arm_6lowpan_bootstrap_functions_set(cur);
01662     cur->mac_parameters->beacon_ind = protocol_6lowpan_analyze_beacon_payload;
01663 
01664     mac_beacon_link_beacon_join_priority_tx_callback_set(cur->id, protocol_6lowpan_beacon_join_priority_tx);
01665     mac_beacon_link_beacon_compare_rx_callback_set(cur->id, protocol_6lowpan_beacon_compare_rx);
01666 
01667     if (net_6lowpan_mode_extension == NET_6LOWPAN_ND_WITHOUT_MLE) {
01668         enable_mle_protocol = false;
01669     }
01670 
01671     cur->mac_security_key_usage_update_cb = arm_6lowpan_security_key_update_cb;
01672     //Allocate MLE class here
01673     //Deallocate old here
01674     mac_neighbor_table_delete(mac_neighbor_info(cur));
01675     mac_description_storage_size_t buffer;
01676     //Read MAC device table sizes
01677     if (cur->mac_api->mac_storage_sizes_get(cur->mac_api, &buffer) != 0) {
01678         return -1;
01679     }
01680 
01681     mac_neighbor_info(cur) = mac_neighbor_table_create(buffer.device_decription_table_size, lowpan_neighbor_entry_remove_notify
01682                                                                         , lowpan_neighbor_entry_nud_notify, cur);
01683     if (!mac_neighbor_info(cur)) {
01684         return -1;
01685     }
01686 
01687     if (enable_mle_protocol) {
01688         if (mle_service_frame_counter_table_allocate(interface_id, buffer.device_decription_table_size)) {
01689             return -1;
01690         }
01691 
01692         if (!etx_storage_list_allocate(cur->id, buffer.device_decription_table_size)) {
01693             return -1;
01694         }
01695 
01696         lowpan_adaptation_interface_etx_update_enable(cur->id);
01697     }
01698 
01699     mle_service_interface_unregister(cur->id);
01700 
01701     if (bootstrap_mode == NET_6LOWPAN_NETWORK_DRIVER || bootstrap_mode == NET_6LOWPAN_SNIFFER) {
01702         enable_mle_protocol = false;
01703         cur->if_up = arm_network_processor_up;
01704         if (bootstrap_mode == NET_6LOWPAN_NETWORK_DRIVER) {
01705             cur->bootsrap_mode = ARM_NWK_BOOTSRAP_MODE_6LoWPAN_RF_ACCESPOINT;
01706             cur->mac_parameters->beacon_ind = NULL; //Drop beacons
01707         } else {
01708             cur->bootsrap_mode = ARM_NWK_BOOTSRAP_MODE_6LoWPAN_RF_SNIFFER;
01709         }
01710         cur->lowpan_info &= ~INTERFACE_NWK_ROUTER_DEVICE;
01711         cur->lowpan_info |= INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE;
01712         arm_nwk_6lowpan_borderrouter_data_free(cur);
01713 
01714         ret_val = 0;
01715         goto bootstrap_finish_check;
01716     } else {
01717         if (enable_mle_protocol) {
01718 #ifdef NO_MLE
01719             return -2;
01720 #else
01721             cur->comm_status_ind_cb = lowpan_comm_status_indication_cb;
01722             if (mle_service_interface_register(cur->id, cur, mle_6lowpan_message_handler, cur->mac,8) != 0) {
01723                 tr_error("Mle Service init Fail");
01724                 return -1;
01725             }
01726 
01727             if (protocol_6lowpan_mle_data_allocate() != 0) {
01728                 tr_error("MLE data allocate Fail");
01729                 return -1;
01730             }
01731 
01732             if (blacklist_init() != 0) {
01733                 tr_error("Blacklist init Fail");
01734                 return -1;
01735             }
01736 
01737             if (mle_6lowpan_data) {
01738                 if (mle_service_interface_token_bucket_settings_set(cur->id, mle_6lowpan_data->token_bucket_size,
01739                     mle_6lowpan_data->token_bucket_rate, mle_6lowpan_data->token_bucket_count) < 0) {
01740                     tr_error("Mle Service tokens set Fail");
01741                     return -1;
01742                 }
01743                 mle_service_set_frame_counter_check(true);
01744                 mle_service_set_accept_invalid_frame_counter(true);
01745             }
01746 #endif
01747         }
01748 
01749         arm_6lowpan_bootstrap_functions_set(cur);
01750         cur->configure_flags &= ~INTERFACE_BOOTSTRAP_DEFINED;
01751         switch (bootstrap_mode) {
01752             case NET_6LOWPAN_HOST:
01753                 protocol_6lowpan_host_init(cur, false);
01754                 ret_val = 0;
01755                 break;
01756             case NET_6LOWPAN_SLEEPY_HOST:
01757                 protocol_6lowpan_host_init(cur, true);
01758                 ret_val = 0;
01759                 break;
01760 
01761             case NET_6LOWPAN_ROUTER:
01762                 protocol_6lowpan_router_init(cur);
01763                 ret_val = 0;
01764                 break;
01765 
01766             case NET_6LOWPAN_BORDER_ROUTER:
01767                 ret_val = arm_nwk_6lowpan_borderrouter_init(cur);
01768                 cur->mac_parameters->beacon_ind = NULL; //Drop beacons
01769                 break;
01770             default:
01771                 break;
01772 
01773         }
01774     }
01775 
01776     bootstrap_finish_check:
01777     if (ret_val == 0) {
01778         /**
01779          *  Do Thread dealloc
01780          */
01781         thread_info_deallocate(cur);
01782         //ADD RPL Support if supported and device is router
01783 #ifdef HAVE_RPL
01784         /**
01785          *  ADD RPL Flag If device is router
01786          */
01787         if (cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) {
01788             //rpl_control_set_domain_on_interface(cur, protocol_6lowpan_rpl_domain, true);
01789             //rpl_control_set_callback(protocol_6lowpan_rpl_domain, protocol_6lowpan_bootstrap_rpl_callback, cur);
01790         }
01791 #endif
01792         cur->configure_flags |= INTERFACE_BOOTSTRAP_DEFINED;
01793         if (enable_mle_protocol) {
01794             cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_MLE;
01795         } else {
01796             cur->lowpan_info &= ~INTERFACE_NWK_BOOTSRAP_MLE;
01797         }
01798     }
01799 
01800     return ret_val;
01801 }
01802 
01803 
01804 static void protocol_6lowpan_bootstrap_icmp_rs_msg_tx(protocol_interface_info_entry_t *cur)
01805 {
01806     buffer_t *buf = icmpv6_build_rs(cur, NULL);
01807 
01808     protocol_push(buf);
01809 }
01810 
01811 void nwk_6lowpan_router_scan_state(protocol_interface_info_entry_t *cur)
01812 {
01813     cur->nwk_rpl_scan_counter = 0;
01814     if (cur->nwk_nd_re_scan_count == 0) {
01815         if (cur->border_router_setup) {
01816             //Activate RS
01817             arm_border_router_ready(cur);
01818         } else {
01819             tr_warn("No ND Router");
01820             nwk_bootsrap_state_update(ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL, cur);
01821         }
01822 
01823     } else {
01824         //Verify is ND Object allocated already
01825         if (!cur->border_router_setup && nd_object_active()) {
01826             tr_debug("Wait response from  ND");
01827         } else {
01828             tr_debug("RS*");
01829             protocol_6lowpan_bootstrap_icmp_rs_msg_tx(cur);
01830             cur->nwk_nd_re_scan_count--;
01831             if (cur->border_router_setup) {
01832                 cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(25, 50);
01833             } else {
01834                 if ((cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) == 0) {
01835                     cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(25, 40);
01836                 } else {
01837                     cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(60, 70);
01838                 }
01839             }
01840         }
01841     }
01842 }
01843 
01844 void nwk_6lowpan_bootstrap_ready(protocol_interface_info_entry_t *cur)
01845 {
01846     if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_ACTIVE) {
01847         uint8_t bootsrap_ready = 0;
01848 
01849         if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION) {
01850 
01851             if (cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) {
01852                 if (pana_ping_notify_msg_tx(cur->mac_parameters->pan_id) == 0) {
01853                     tr_warn("PING TX fail");
01854                 } else {
01855                     bootsrap_ready = 1;
01856                 }
01857 
01858             } else {
01859                 if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_MLE) {
01860 #ifndef NO_MLE
01861                     tr_debug("MLE Parent Advertisment");
01862                     if (protocol_6lowpan_mle_neigh_advertise(cur) == 0) {
01863                         bootsrap_ready = 1;
01864                     } else {
01865                         tr_warn("MLE Host Parent Advert TX fail");
01866                     }
01867 #endif
01868                 } else {
01869                     bootsrap_ready = 1;
01870                 }
01871             }
01872         } else {
01873             bootsrap_ready = 1;
01874 
01875         }
01876         if (bootsrap_ready) {
01877             if (cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) {
01878                 // Updates beacon
01879                 beacon_join_priority_update(cur->id);
01880                 lowpan_bootstrap_pan_control(cur, true);
01881             }
01882             nwk_bootsrap_state_update(ARM_NWK_BOOTSTRAP_READY, cur);
01883         } else {
01884             cur->nwk_bootstrap_state = ER_BOOTSRAP_DONE;
01885             cur->bootsrap_state_machine_cnt = 2;
01886         }
01887     }
01888 }
01889 
01890 void protocol_6lowpan_link_advertise_handle(nd_router_t *cur, protocol_interface_info_entry_t *cur_interface, uint16_t tick)
01891 {
01892     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)) {
01893 #ifndef NO_MLE
01894         if (cur->mle_advert_timer) {
01895             if (cur->mle_advert_timer > tick) {
01896                 cur->mle_advert_timer -= tick;
01897 
01898             } else {
01899                 if (protocol_6lowpan_mle_neigh_advertise(cur_interface) == 0) {
01900 
01901                     if (cur_interface->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE) {
01902                         cur->mle_advert_timer = 0;
01903                     } else {
01904                         cur->mle_advert_timer = 155;
01905 
01906                         if (mle_6lowpan_data) {
01907                             uint16_t period = mle_6lowpan_data->router_lifetime / 4;
01908                             if (period > 640) {
01909                                 period = 640;
01910                             }
01911                             period *= 10; //seconds ticks --> 100ms ticks
01912                             //set 0.9 - 1.1 * period
01913                             cur->mle_advert_timer = randLIB_randomise_base(period, LOWPAN_RAND_LOW, LOWPAN_RAND_HIGH);
01914                         }
01915                     }
01916                 } else {
01917                     cur->mle_advert_timer = 2;
01918                 }
01919 
01920                 if (cur->mle_purge_timer) {
01921                     cur->mle_purge_timer -= 1;
01922                 } else {
01923                     if (mle_6lowpan_data && mle_6lowpan_data->nbr_of_neigh_max != 0) {
01924                         uint16_t mle_neigh_cnt = mle_class_active_neigh_counter(cur_interface);
01925                         if (mle_neigh_cnt > (mle_6lowpan_data->nbr_of_neigh_max - MLE_NEIGHBOR_PURGE_NBR)) {
01926                             protocol_6lowpan_mle_purge_neighbors(cur_interface, MLE_NEIGHBOR_PURGE_NBR, true);
01927                         }
01928 
01929                         if (mle_neigh_cnt > (mle_6lowpan_data->nbr_of_neigh_upper_threshold - MLE_NEIGHBOR_PURGE_NBR)) {
01930                             protocol_6lowpan_mle_purge_neighbors(cur_interface, MLE_NEIGHBOR_PURGE_NBR, false);
01931                         }
01932 
01933                         uint16_t mle_purge_timer;
01934                         /* From 1.0 to 1.5 * MLE_NEIGHBOR_PURGE_TIMER */
01935                         mle_purge_timer = randLIB_randomise_base(MLE_NEIGHBOR_PURGE_TIMER_TIMEOUT, 0x8000, 0xC000);
01936                         cur->mle_purge_timer = mle_purge_timer;
01937                     }
01938                 }
01939                 // Updates blacklist timer
01940                 blacklist_ttl_update(1);
01941             }
01942         }
01943 #endif
01944     } else {
01945         cur->mle_advert_timer = 0;
01946     }
01947 }
01948 
01949 static void protocol_6lowpan_nd_ready(protocol_interface_info_entry_t *cur)
01950 {
01951     if ((cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_ACTIVE)) {
01952         tr_debug("ND BS ready");
01953         bootsrap_next_state_kick(ER_BIND_COMP, cur);
01954         clear_power_state(ICMP_ACTIVE);
01955         cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY;
01956     } else {
01957         tr_debug("RE ND ready");
01958         clear_power_state(ICMP_ACTIVE);
01959         mac_data_poll_protocol_poll_mode_disable(cur);
01960         //TRIG MLE Challenge for Normal Host
01961         if ((cur->lowpan_info & (INTERFACE_NWK_ROUTER_DEVICE | INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE | INTERFACE_NWK_BOOTSRAP_MLE)) == INTERFACE_NWK_BOOTSRAP_MLE) {
01962             //TRIG Only Normal Host
01963 #ifndef NO_MLE
01964             //GET Cordinator MLE Entry
01965             addrtype_t addrType;
01966             uint8_t tempAddr[8];
01967             addrType = mac_helper_coordinator_address_get(cur, tempAddr);
01968             mac_neighbor_table_entry_t * neig_info = mac_neighbor_table_address_discover(mac_neighbor_info(cur), tempAddr, addrType);
01969 
01970             if (neig_info) {
01971                 if (neig_info->lifetime  > MLE_TABLE_CHALLENGE_TIMER) {
01972                     neig_info->lifetime   = (MLE_TABLE_CHALLENGE_TIMER + 1);
01973                 }
01974             }
01975 #endif
01976         }
01977     }
01978 }
01979 
01980 static void protocol_6lowpan_address_reg_ready(protocol_interface_info_entry_t *cur_interface)
01981 {
01982     nd_router_t *cur;
01983     cur = nd_get_object_by_nwk_id(cur_interface->nwk_id);
01984 
01985     if(!cur) {
01986         return;
01987     }
01988 
01989     cur->nd_timer = 10;
01990     cur->ns_forward_timer = 0;
01991 
01992     uint16_t mle_timer = 0;
01993     protocol_6lowpan_nd_ready(cur_interface);
01994     if (cur_interface->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) {
01995         addr_add_router_groups(cur_interface);
01996         addr_add_group(cur_interface, ADDR_REALM_LOCAL_ALL_ROUTERS);
01997         icmpv6_radv_enable(cur_interface);
01998         icmpv6_restart_router_advertisements(cur_interface, cur->border_router);
01999         /* Stop the ND revalidate timer - this means we don't do RS again */
02000         cur->nd_re_validate = 0;
02001         mle_timer = 300;
02002     } else {
02003         if (cur_interface->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE) {
02004             mac_data_poll_protocol_poll_mode_decrement(cur_interface);
02005             mle_timer = 20;
02006         } else {
02007             mle_timer = 155;
02008         }
02009     }
02010     if (cur_interface->lowpan_info & INTERFACE_NWK_BOOTSRAP_MLE) {
02011         if (cur->mle_advert_timer == 0) {
02012             cur->mle_advert_timer = mle_timer;
02013             cur->mle_purge_timer = MLE_NEIGHBOR_PURGE_TIMER_TIMEOUT;
02014         }
02015     } else {
02016         cur->mle_advert_timer = 0;
02017     }
02018 }
02019 
02020 void protocol_6lowpan_bootstrap_nd_ready(protocol_interface_info_entry_t *cur_interface)
02021 {
02022 
02023     tr_debug("ND Ready");
02024 
02025 
02026 
02027     if (cur_interface->lowpan_address_mode == NET_6LOWPAN_GP64_ADDRESS) {
02028         protocol_6lowpan_address_reg_ready(cur_interface);
02029     } else {
02030         //Here we need to verify address mode
02031         tr_debug("Synch MAC16 with parent");
02032         if (protocol_6lowpan_parent_address_synch(cur_interface, true) != 0 ) {
02033             nwk_bootsrap_state_update(ARM_NWK_NWK_CONNECTION_DOWN, cur_interface);
02034         }
02035     }
02036 
02037 
02038 }
02039 
02040 #ifdef HAVE_RPL
02041 
02042 static void protocol_6lowpan_bootstrap_rpl_callback(rpl_event_t event, void *handle)
02043 {
02044 
02045     protocol_interface_info_entry_t *cur = handle;
02046     if (!cur->rpl_domain || cur->interface_mode != INTERFACE_UP) {
02047         return;
02048     }
02049     switch (event) {
02050         case RPL_EVENT_DAO_DONE:
02051             if ((cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_ACTIVE)) {
02052                 bootsrap_next_state_kick(ER_BOOTSRAP_DONE, cur);
02053                 clear_power_state(ICMP_ACTIVE);
02054             } else if (cur->nwk_bootstrap_state == ER_RPL_LOCAL_REPAIR) {
02055                 // Updates beacon
02056                 cur->bootsrap_state_machine_cnt = 0;
02057                 cur->nwk_bootstrap_state = ER_BOOTSRAP_DONE;
02058                 beacon_join_priority_update(cur->id);
02059                 lowpan_bootstrap_pan_control(cur, true);
02060             }
02061             break;
02062 
02063         case RPL_EVENT_LOCAL_REPAIR_START:
02064             if (!(cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_ACTIVE)) {
02065                 tr_error("RPL Local repair started");
02066                 lowpan_bootstrap_pan_control(cur, false);
02067                 cur->bootsrap_state_machine_cnt = 0;
02068                 cur->nwk_bootstrap_state = ER_RPL_LOCAL_REPAIR;
02069             }
02070             break;
02071 
02072         case RPL_EVENT_LOCAL_REPAIR_NO_MORE_DIS:
02073             tr_error("RPL Local repair fail-->interface to idle");
02074             nwk_bootsrap_state_update(ARM_NWK_NWK_CONNECTION_DOWN, cur);
02075             break;
02076     }
02077 }
02078 
02079 /**
02080  * \brief Send ICMP RPL DIS message.
02081  *
02082  * \return 0 , buffer_allocation fail & 1 message sent
02083  */
02084 uint8_t nwk_bootstrap_icmp_rpl_dis_msg_tx(protocol_interface_info_entry_t *cur)
02085 {
02086     if (cur->rpl_domain) {
02087         rpl_control_transmit_dis(cur->rpl_domain, cur, 0, 0, NULL, 0, NULL);
02088         return 1;
02089     }
02090 
02091     return 0;
02092 }
02093 
02094 /**
02095  * \brief Send ICMP RPL DIS message to bootstrap coordinator
02096  *
02097  * \return 0 , buffer_allocation fail & 1 message sent
02098  */
02099 static uint8_t nwk_bootstrap_icmp_rpl_dis_coord_msg_tx(protocol_interface_info_entry_t *cur)
02100 {
02101     if (!cur->rpl_domain) {
02102         return 0;
02103     }
02104 
02105     uint8_t coord_address[16];
02106     if (protocol_6lowpan_interface_get_link_local_cordinator_address(cur, coord_address) != 0) {
02107         tr_debug("Unicast DIS no coord");
02108         return 0;
02109     }
02110 
02111     rpl_control_transmit_dis(cur->rpl_domain, cur, 0, 0, NULL, 0, coord_address);
02112     return 1;
02113 }
02114 
02115 static void nwk_rpl_dio_scan(protocol_interface_info_entry_t *cur)
02116 {
02117     if (cur->nwk_rpl_scan_counter < MAX_MC_DIS_COUNT) {
02118         if (nwk_bootstrap_icmp_rpl_dis_msg_tx(cur)) {
02119             cur->bootsrap_state_machine_cnt = 45 << cur->nwk_rpl_scan_counter;
02120             cur->nwk_rpl_scan_counter++;
02121             tr_debug("MC_DIS\n");
02122             cur->nwk_bootstrap_state = ER_RPL_SCAN;
02123         } else {
02124             cur->bootsrap_state_machine_cnt = 3;
02125         }
02126     } else {
02127         //GivE Up Bootsrap
02128         nwk_bootsrap_state_update(ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL, cur);
02129     }
02130 }
02131 
02132 
02133 void nwk_6lowpan_rpl_router_discover(protocol_interface_info_entry_t *cur)
02134 {
02135     if (cur->rpl_domain) {
02136         tr_debug("MC DIS Force");
02137         if (nwk_bootstrap_icmp_rpl_dis_msg_tx(cur)) {
02138             cur->nwk_bootstrap_state = ER_RPL_SCAN;
02139             cur->bootsrap_state_machine_cnt = 55;
02140         } else {
02141             cur->nwk_bootstrap_state = ER_RPL_MC;
02142             cur->bootsrap_state_machine_cnt = 15;
02143         }
02144     } else {
02145         cur->nwk_bootstrap_state = ER_BOOTSRAP_DONE;
02146         nwk_6lowpan_bootstrap_ready(cur);
02147     }
02148 }
02149 
02150 void nwk_6lowpan_rpl_router_result_check(protocol_interface_info_entry_t *cur)
02151 {
02152     if (cur->rpl_domain) {
02153         if (rpl_control_have_dodag(cur->rpl_domain)) {
02154             tr_debug("UNI DIS");
02155             cur->bootsrap_state_machine_cnt = 0;
02156         } else {
02157             nwk_rpl_dio_scan(cur);
02158         }
02159     } else {
02160         cur->nwk_bootstrap_state = ER_BOOTSRAP_DONE;
02161         nwk_6lowpan_bootstrap_ready(cur);
02162     }
02163 }
02164 #endif
02165 
02166 void nwk_6lowpan_nd_address_registartion_ready(protocol_interface_info_entry_t *cur)
02167 {
02168     tr_debug("ND Ready!!");
02169     cur->nwk_rpl_scan_counter = 0;
02170 
02171 #ifndef NO_MLE
02172     if (cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) {
02173         if (protocol_6lowpan_router_multicast_synch(cur) != 0) {
02174             tr_debug("Router link request start fail");
02175             nwk_bootsrap_state_update(ARM_NWK_NWK_CONNECTION_DOWN, cur);
02176         }
02177 #ifdef HAVE_RPL
02178         if (protocol_6lowpan_rpl_domain) {
02179             // arm_nwk_6lowpan_rpl_dodag_poison from a previous connection may have left force_leaf set
02180             rpl_control_force_leaf(protocol_6lowpan_rpl_domain, false);
02181             rpl_control_set_domain_on_interface(cur, protocol_6lowpan_rpl_domain, true);
02182             rpl_control_set_callback(protocol_6lowpan_rpl_domain, protocol_6lowpan_bootstrap_rpl_callback, cur);
02183         }
02184         // Send unicast DIS to coordinator
02185         nwk_bootstrap_icmp_rpl_dis_coord_msg_tx(cur);
02186 #endif /* HAVE_RPL */
02187     } else {
02188         //No point to update link
02189         if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_SLEEPY_HOST || cur->lowpan_address_mode != NET_6LOWPAN_GP64_ADDRESS) {
02190             if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_SLEEPY_HOST) {
02191                 cur->lowpan_info |= INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE;
02192                 tr_debug("Enable Poll state");
02193                 mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, false);
02194                 mac_data_poll_init(cur);
02195                 mac_data_poll_init_protocol_poll(cur);
02196             }
02197             if (protocol_6lowpan_parent_address_synch(cur, false) != 0) {
02198                 nwk_bootsrap_state_update(ARM_NWK_NWK_CONNECTION_DOWN, cur);
02199             }
02200         } else {
02201             cur->nwk_bootstrap_state = ER_BOOTSRAP_DONE;
02202             nwk_6lowpan_bootstrap_ready(cur);
02203         }
02204     }
02205 #else
02206 #ifdef HAVE_RPL
02207     cur->nwk_bootstrap_state = ER_RPL_SCAN;
02208     nwk_6lowpan_rpl_router_result_check(cur);
02209 #else
02210     cur->nwk_bootstrap_state = ER_BOOTSRAP_DONE;
02211     nwk_6lowpan_bootstrap_ready(cur);
02212 #endif
02213 #endif
02214 }
02215 #ifdef PANA
02216 void nwk_6lowpan_pana_key_pull(protocol_interface_info_entry_t *cur)
02217 {
02218     //REG GP16 address
02219     if (pana_ping_notify_msg_tx(cur->mac_parameters->pan_id) == 0) {
02220         tr_warn("PING TX fail");
02221         cur->nwk_bootstrap_state = ER_PANA_PING;
02222         cur->bootsrap_state_machine_cnt = 2;
02223     }
02224 }
02225 #endif
02226 
02227 #ifndef NO_MLE
02228 
02229 #ifdef PANA
02230 void nwk_6lowpan_bootsrap_pana_authentication_cb(bool processSuccesfully, protocol_interface_info_entry_t *cur)
02231 {
02232     if (processSuccesfully) {
02233         bootsrap_next_state_kick(ER_PANA_AUTH_DONE, cur);
02234     } else {
02235         bootsrap_next_state_kick(ER_PANA_AUTH_ERROR, cur);
02236 
02237     }
02238 }
02239 
02240 static void nwk_6lowpan_bootsrap_pana_authentication_start(protocol_interface_info_entry_t *cur)
02241 {
02242     uint8_t temp_coordinator_address[16];
02243     pana_tls_setup_s setup;
02244     sec_suite_t *suite = 0;
02245     tr_debug("Wake Pana by Bootsrap");
02246     protocol_6lowpan_interface_get_link_local_cordinator_address(cur, temp_coordinator_address);
02247     //Release old before copy new
02248     if (cur->pana_sec_info_temp == 0) {
02249         tr_debug("Allocate Pana auth Info");
02250         cur->pana_sec_info_temp = ns_dyn_mem_alloc(sizeof(auth_info_t));
02251     }
02252     if (cur->if_lowpan_security_params->pana_params) {
02253         setup.psk_key_id = cur->if_lowpan_security_params->pana_params->psk_key_id;
02254 
02255         switch (cur->if_lowpan_security_params->pana_params->nwk_chipher_mode) {
02256             case NET_TLS_PSK_CIPHER:        /**< Network Authentication support only PSK */
02257                 setup.security_support = SEC_CIPHERSUITE_PSK;
02258                 break;
02259 
02260             case NET_TLS_ECC_CIPHER:        /**< Network Authentication support only ECC */
02261                 setup.security_support = SEC_CIPHERSUITE_ECC;
02262                 break;
02263             case NET_TLS_PSK_AND_ECC_CIPHER:
02264                 setup.security_support = SEC_CIPHERSUITE_PSK | SEC_CIPHERSUITE_ECC;
02265                 break;
02266         }
02267 
02268         setup.pan_id = cur->mac_parameters->pan_id;
02269         suite = pana_client_init(cur->pana_sec_info_temp, temp_coordinator_address, &setup);
02270 
02271     }
02272     if (suite) {
02273         //SET address
02274         //SET CORD Address
02275         nd_router_t   *object = nd_get_pana_address();
02276         cur->nwk_bootstrap_state = ER_PANA_AUTH;
02277         cur->bootsrap_state_machine_cnt = 0;
02278         if (object) {
02279             icmp_nd_set_nd_def_router_address(suite->session_address, object);
02280 
02281             tr_debug("ND Router adr: %s", trace_ipv6(suite->session_address));
02282 
02283             //SET CORD ADDRESS
02284             if (memcmp(&suite->session_address[8], ADDR_SHORT_ADR_SUFFIC, 6) == 0) {
02285                 mac_helper_coordinator_address_set(cur, ADDR_802_15_4_SHORT , &(suite->session_address[14]));
02286             } else {
02287                 suite->session_address[8] ^= 2;
02288                 mac_helper_coordinator_address_set(cur, ADDR_802_15_4_LONG , &(suite->session_address[8]));
02289                 suite->session_address[8] ^= 2;
02290             }
02291         } else {
02292             tr_debug("Use Mac Coordinator");
02293         }
02294         suite->session_port = UDP_PORT_PANA;
02295         suite->interface = cur;
02296     } else {
02297         cur->nwk_bootstrap_state = ER_PANA_AUTH_ERROR;
02298         cur->bootsrap_state_machine_cnt = 1;
02299     }
02300 }
02301 #endif
02302 
02303 #endif
02304 
02305 static void coordinator_black_list(protocol_interface_info_entry_t *cur)
02306 {
02307     uint8_t coord_pan_address[10];
02308     addrtype_t cord_adr_type = mac_helper_coordinator_address_get(cur, coord_pan_address +2);
02309 
02310     if (cord_adr_type != ADDR_NONE ) {
02311         uint16_t pana_id = mac_helper_panid_get(cur);
02312         common_write_16_bit(pana_id, coord_pan_address);
02313         if (cord_adr_type == ADDR_802_15_4_SHORT ) {
02314             memset(coord_pan_address + 4, 0, 6);
02315         }
02316 
02317         pan_cordinator_blacklist_pan_set(&cur->pan_cordinator_black_list, coord_pan_address, 300);
02318     }
02319 }
02320 
02321 static void nwk_6lowpan_network_authentication_fail(protocol_interface_info_entry_t *cur)
02322 {
02323     nwk_scan_params_t *scan_params =
02324             &cur->mac_parameters->nwk_scan_params;
02325 
02326     tr_warn("Pana Auhth er");
02327 
02328     scan_params->nwk_cur_active = mac_helper_free_pan_descriptions(scan_params->nwk_cur_active);
02329     //Black List coordinator
02330     coordinator_black_list(cur);
02331 
02332     nwk_bootsrap_state_update(ARM_NWK_AUHTENTICATION_FAIL, cur);
02333 }
02334 
02335 
02336 static void nwk_protocol_network_key_set_from_pana(protocol_interface_info_entry_t *cur)
02337 {
02338     uint8_t *key_ptr = pana_key_get(cur->pana_sec_info_temp->network_key);
02339 
02340     if (key_ptr) {
02341         mac_helper_security_default_key_set(cur, (key_ptr + 16), cur->pana_sec_info_temp->key_id, MAC_KEY_ID_MODE_IDX);
02342         mle_service_security_set_security_key(cur->id, key_ptr, cur->pana_sec_info_temp->key_id, true);
02343         if (cur->nwk_wpan_nvm_api) {
02344             cur->nwk_wpan_nvm_api->nvm_params_update_cb(cur->nwk_wpan_nvm_api, true);
02345         }
02346     }
02347 }
02348 
02349 uint8_t *protocol_6lowpan_mle_service_security_notify_cb(int8_t interface_id, mle_security_event_t event, uint8_t keyId)
02350 {
02351     (void)keyId;
02352     protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(interface_id);
02353     if (!interface) {
02354         return NULL;
02355     }
02356     switch (event) {
02357         case MLE_SEC_MAX_FRAME_COUNTER_REACHED :
02358 
02359             break;
02360 
02361         case MLE_SEC_KEY_UPDATE_NOTIFY :
02362             //Call MAC update
02363             mac_helper_security_key_swap_next_to_default(interface);
02364 
02365             break;
02366 
02367         case MLE_SEC_UNKNOWN_KEY :
02368             break;
02369     }
02370     return NULL;
02371 }
02372 
02373 static void nwk_protocol_network_key_init_from_pana(protocol_interface_info_entry_t *cur)
02374 {
02375     uint8_t *key_ptr = pana_key_get(cur->pana_sec_info_temp->network_key);
02376 
02377     if (key_ptr) {
02378         mac_helper_security_default_key_set(cur, (key_ptr + 16), cur->pana_sec_info_temp->key_id, MAC_KEY_ID_MODE_IDX);
02379         //mac_security_interface_link_frame_counter_reset(cur->id);
02380         mac_helper_default_security_level_set(cur, SEC_ENC_MIC32);
02381         mac_helper_default_security_key_id_mode_set(cur,MAC_KEY_ID_MODE_IDX);
02382         //Init MLE Frame counter and key's and security
02383         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);
02384         mle_service_security_set_security_key(cur->id, key_ptr, cur->pana_sec_info_temp->key_id, true);
02385         mle_service_security_set_frame_counter(cur->id, cur->if_lowpan_security_params->mle_security_frame_counter);
02386     }
02387 }
02388 
02389 static void nwk_6lowpan_network_authentication_done(protocol_interface_info_entry_t *cur)
02390 {
02391     if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_ACTIVE) {
02392         mac_helper_free_scan_confirm(&cur->mac_parameters->nwk_scan_params);
02393 
02394         if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION) {
02395             nwk_protocol_network_key_init_from_pana(cur);
02396         } else {
02397             tr_debug("SET NO security");
02398             mac_helper_default_security_level_set(cur, SEC_NONE);
02399         }
02400 
02401 #ifndef NO_MLE
02402         if (protocol_6lowpan_parent_link_req(cur) != 0) {
02403             tr_debug("Link request start fail");
02404         }
02405 #else
02406         pan_coordinator_blacklist_free(&cur->pan_cordinator_black_list);
02407         cur->nwk_bootstrap_state = ER_SCAN;
02408         nwk_6lowpan_router_scan_state(cur);
02409 #endif
02410     } else {
02411         mac_data_poll_protocol_poll_mode_disable(cur);
02412         if ((cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) == 0) {
02413             tr_debug("PULL kEY Done by Host");
02414             cur->nwk_bootstrap_state = ER_BOOTSRAP_DONE;
02415             nwk_6lowpan_bootstrap_ready(cur);
02416         } else {
02417             tr_debug("PULL kEY Done by Router");
02418 #ifdef PANA
02419             cur->nwk_bootstrap_state = ER_PANA_PING;
02420             nwk_6lowpan_pana_key_pull(cur);
02421 #endif
02422         }
02423 
02424         nwk_protocol_network_key_set_from_pana(cur);
02425 #ifndef NO_TLS
02426 #endif
02427 
02428     }
02429 }
02430 
02431 
02432 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)
02433 {
02434     mlme_start_t start_req;
02435     memset(&start_req, 0, sizeof(mlme_start_t));
02436     mac_helper_coordinator_address_set(interface, (addrtype_t)pan_descriptor->CoordAddrMode, pan_descriptor->CoordAddress);
02437 
02438     interface->mac_parameters->mac_channel = pan_descriptor->LogicalChannel;
02439     interface->mac_parameters->pan_id = pan_descriptor->CoordPANId;
02440     if (interface->nwk_wpan_nvm_api) {
02441         wpan_nvm_params_t *params = interface->nwk_wpan_nvm_api->nvm_params_get_cb(interface->nwk_wpan_nvm_api, pan_descriptor->CoordPANId);
02442         interface->if_lowpan_security_params->mle_security_frame_counter = params->mle_securit_counter;
02443         //SET MAC and MLE security frame counters
02444         mle_service_security_set_frame_counter(interface->id, params->mle_securit_counter);
02445         mac_helper_link_frame_counter_set(interface->id, params->mac_security_frame_counter);
02446     }
02447 
02448     start_req.PANId = pan_descriptor->CoordPANId;
02449     start_req.LogicalChannel = pan_descriptor->LogicalChannel;
02450     start_req.ChannelPage = 0;
02451     start_req.BeaconOrder = pan_descriptor->SuperframeSpec[0] >> 4;
02452     start_req.SuperframeOrder = pan_descriptor->SuperframeSpec[0] & 0x0f;
02453     //SET Beacon Payload
02454     uint8_t *b_ptr = mac_helper_beacon_payload_reallocate(interface, beacon_length);
02455     if (!b_ptr) {
02456         tr_error("Beacon Payload allocate Fail");
02457         bootsrap_next_state_kick(ER_BOOTSTRAP_SCAN_FAIL, interface);
02458         return false;
02459     }
02460     memcpy(b_ptr, beacon_payload, beacon_length);
02461     mac_helper_beacon_payload_register(interface);
02462     //Start and set pan-id
02463     interface->mac_api->mlme_req(interface->mac_api, MLME_START, &start_req);
02464     mac_helper_panid_set(interface, pan_descriptor->CoordPANId);
02465 
02466     return true;
02467 }
02468 
02469 bool protocol_6lowpan_bootsrap_start(protocol_interface_info_entry_t *interface)
02470 {
02471     net_load_balance_internal_state_activate(interface, false);
02472 
02473     //SET allways RX ON Idle device by default
02474     mac_helper_pib_boolean_set(interface, macRxOnWhenIdle, true);
02475     interface->lowpan_info &=  ~INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE;
02476 
02477     mac_data_poll_init(interface);
02478     mac_helper_mac16_address_set(interface, 0xffff);
02479     tr_debug("Mac Ready");
02480     interface->nwk_nd_re_scan_count = 2;
02481 
02482     if (interface->if_lowpan_security_params->nwk_security_mode == NET_SEC_MODE_PSK_LINK_SECURITY) {
02483         tr_debug("SET Security Mode");
02484         mac_helper_default_security_level_set(interface, interface->mac_parameters->mac_configured_sec_level);
02485         mac_helper_default_security_key_id_mode_set(interface,MAC_KEY_ID_MODE_IDX);
02486     }
02487 
02488     //Check first pana and then MLE and else start RS scan pahse
02489     if (interface->lowpan_info & INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION) {
02490 #ifdef PANA
02491         nwk_6lowpan_bootsrap_pana_authentication_start(interface);
02492         tr_debug("Pana auth");
02493 #else
02494         bootsrap_next_state_kick(ER_BOOTSTRAP_SCAN_FAIL, interface);
02495         return false;
02496 #endif
02497     } else if (interface->lowpan_info & INTERFACE_NWK_BOOTSRAP_MLE) {
02498         if (protocol_6lowpan_parent_link_req(interface) != 0) {
02499             bootsrap_next_state_kick(ER_BOOTSTRAP_SCAN_FAIL, interface);
02500             return false;
02501         }
02502     } else {
02503         bootsrap_next_state_kick(ER_SCAN, interface);
02504     }
02505     return true;
02506 }
02507 
02508 
02509 void protocol_6lowpan_mac_scan_confirm(int8_t if_id, const mlme_scan_conf_t* conf)
02510 {
02511     nwk_pan_descriptor_t *result;
02512     nwk_pan_descriptor_t *best;
02513     protocol_interface_info_entry_t *interface = NULL;
02514 
02515     if (conf->ScanType != MAC_ACTIVE_SCAN) {
02516         return;
02517     }
02518 
02519     interface = protocol_stack_interface_info_get_by_id(if_id);
02520     if (!interface) {
02521         tr_debug("Mac scan confirm:Unknow Interface");
02522         return;
02523     }
02524     bool is_border_router = false;
02525     if (interface->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
02526         is_border_router = true;
02527     }
02528 
02529     interface->mac_parameters->nwk_scan_params.active_scan_active = false;
02530 
02531     result = arm_net_get_scanned_nwk_list(if_id);
02532     if (!result || !conf->ResultListSize) {
02533         tr_debug("Mac scan confirm:No Beacons");
02534         if (is_border_router == false) {
02535             bootsrap_next_state_kick(ER_BOOTSTRAP_SCAN_FAIL, interface);
02536             return;
02537         }
02538     }
02539 
02540     //Analyze Best Result
02541     best = mac_helper_select_best_lqi(result);
02542     mac_helper_drop_selected_from_the_scanresult(&interface->mac_parameters->nwk_scan_params, best);
02543 
02544     bool link_start_ok = false;
02545     if (is_border_router == false) {
02546         link_start_ok = protocol_6lowpan_bootsrap_link_set(interface, best->pan_descriptor, best->beacon_payload, best->beacon_length);
02547     }
02548 
02549     mac_helper_free_scan_confirm(&interface->mac_parameters->nwk_scan_params);
02550 
02551     best = mac_helper_free_pan_descriptions(best);
02552 
02553     if (link_start_ok) {
02554         protocol_6lowpan_bootsrap_start(interface);
02555     }
02556 
02557     if (is_border_router == true) {
02558         if (interface->nwk_bootstrap_state == ER_WARM_ACTIVE_SCAN) {
02559             border_router_start(interface, true);
02560             interface->bootsrap_state_machine_cnt = 0;
02561             interface->nwk_bootstrap_state = ER_BOOTSRAP_DONE;
02562         } else {
02563             border_router_start(interface, false);
02564         }
02565 
02566     }
02567 }
02568 
02569 void bootstrap_timer_handle(uint16_t ticks)
02570 {
02571     (void)ticks;
02572     ns_list_foreach(protocol_interface_info_entry_t, cur, &protocol_interface_info_list) {
02573         if (cur->nwk_id == IF_6LoWPAN) {
02574             if (cur->nwk_bootstrap_state == ER_ACTIVE_SCAN || cur->nwk_bootstrap_state == ER_WARM_ACTIVE_SCAN) {
02575                 // Retransmit Scan request
02576                 bootsrap_next_state_kick(cur->nwk_bootstrap_state, cur);
02577                 tr_error("Restart active scan");
02578             } else {
02579                 // Retransmit Start request
02580                 mlme_start_t start_req;
02581                 memset(&start_req, 0, sizeof(mlme_start_t));
02582                 start_req.PANId = cur->border_router_setup->mac_panid;
02583                 start_req.LogicalChannel = cur->mac_parameters->mac_channel;
02584                 start_req.ChannelPage = 0;
02585                 start_req.BeaconOrder = 0x0f;
02586                 start_req.SuperframeOrder = 0x0f;
02587                 start_req.PANCoordinator = 1;
02588                 if( cur->mac_api ){
02589                     cur->mac_api->mlme_req(cur->mac_api, MLME_START, (void*)&start_req);
02590                     tr_error("Restart MAC");
02591                 }
02592             }
02593         }
02594     }
02595 }
02596 
02597 void protocol_6lowpan_bootstrap(protocol_interface_info_entry_t *cur)
02598 {
02599     switch (cur->nwk_bootstrap_state) {
02600         case ER_ACTIVE_SCAN:
02601         case ER_WARM_ACTIVE_SCAN:
02602             tr_debug("Start Active Scan");
02603             cur->mac_parameters->nwk_scan_params.stack_chan_list = cur->mac_parameters->mac_channel_list;
02604 
02605             mlme_scan_t req;
02606             mac_create_scan_request(MAC_ACTIVE_SCAN, &cur->mac_parameters->mac_channel_list, cur->mac_parameters->nwk_scan_params.scan_duration, &req);
02607             if( cur->mac_api ){
02608                 cur->scan_cb = protocol_6lowpan_mac_scan_confirm;
02609                 cur->mac_parameters->nwk_scan_params.active_scan_active = true;
02610                 if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
02611                     protocol_timer_start(PROTOCOL_TIMER_BOOTSTRAP_TIM, bootstrap_timer_handle, BOOTSTRAP_SCAN_TIMEOUT);
02612                 }
02613                 cur->mac_api->mlme_req(cur->mac_api, MLME_SCAN, &req);
02614             }
02615             break;
02616 
02617         case ER_SCAN:
02618             //LED1_TOGGLE();
02619             nwk_6lowpan_router_scan_state(cur);
02620             break;
02621 
02622         case ER_PANA_AUTH_ERROR:
02623             nwk_6lowpan_network_authentication_fail(cur);
02624             break;
02625 
02626         case ER_PANA_AUTH_DONE:
02627             nwk_6lowpan_network_authentication_done(cur);
02628             break;
02629 
02630         case ER_BIND_COMP:
02631             nwk_6lowpan_nd_address_registartion_ready(cur);
02632             break;
02633 
02634 #ifdef HAVE_RPL
02635 
02636         case ER_RPL_MC:
02637             nwk_6lowpan_rpl_router_discover(cur);
02638             break;
02639 
02640         case ER_RPL_SCAN:
02641             nwk_6lowpan_rpl_router_result_check(cur);
02642             break;
02643 #endif
02644         case ER_BOOTSRAP_DONE:
02645             nwk_6lowpan_bootstrap_ready(cur);
02646             break;
02647 
02648         case ER_PARENT_SYNCH_LOST:
02649             tr_debug("-->Parent synch Lose");
02650             nwk_bootsrap_state_update(ARM_NWK_NWK_PARENT_POLL_FAIL, cur);
02651             break;
02652 
02653         case ER_BOOTSTRAP_CONNECTION_DOWN:
02654             nwk_bootsrap_state_update(ARM_NWK_NWK_CONNECTION_DOWN, cur);
02655             break;
02656 
02657         case ER_BOOTSTRAP_IP_ADDRESS_ALLOC_FAIL:
02658             nwk_bootsrap_state_update(ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL, cur);
02659             tr_info("-->idle");
02660             break;
02661 
02662         case ER_BOOTSTRAP_DAD_FAIL:
02663             nwk_bootsrap_state_update(ARM_NWK_DUPLICATE_ADDRESS_DETECTED, cur);
02664             break;
02665 
02666         case ER_BOOTSTRAP_SCAN_FAIL:
02667             tr_debug("Network Bootsrap Start Fail");
02668             nwk_bootsrap_state_update(ARM_NWK_NWK_SCAN_FAIL, cur);
02669             break;
02670 #ifdef PANA
02671         case ER_PANA_PING:
02672             nwk_6lowpan_pana_key_pull(cur);
02673             break;
02674 #endif
02675         case ER_MLE_LINK_REQ:
02676             //No need to do anything in this case
02677             break;
02678         default:
02679             tr_error("Unknow state %d", cur->nwk_bootstrap_state);
02680 
02681     }
02682 }
02683 
02684 void protocol_6lowpan_nd_borderrouter_connection_down(protocol_interface_info_entry_t *interface)
02685 {
02686     /*if (rpl_object_poisons() == 0) ??? */ {
02687         mac_helper_mac16_address_set(interface, 0xffff);
02688 
02689         //TRIG Event for ND connection Down
02690         bootsrap_next_state_kick(ER_BOOTSTRAP_IP_ADDRESS_ALLOC_FAIL, interface);
02691     }
02692 }
02693 
02694 void protocol_6lowpan_bootstrap_re_start(protocol_interface_info_entry_t *interface)
02695 {
02696     mac_helper_mac16_address_set(interface, 0xffff);
02697     arm_6lowpan_bootstrap_init(interface);
02698     tr_info("-->Bootsrap");
02699 }
02700 
02701 uint8_t *protocol_6lowpan_nd_border_router_address_get(nwk_interface_id nwk_id)
02702 {
02703     nd_router_t   *object = nd_get_object_by_nwk_id(nwk_id);
02704     if (object) {
02705         return object->border_router;
02706     }
02707     return 0;
02708 }
02709 
02710 uint8_t protocol_6lowpan_rf_link_scalability_from_lqi(uint8_t lqi)
02711 {
02712     uint8_t i = 16;
02713     if (lqi >= 240) {
02714         i = 1;
02715     } else {
02716         lqi /= 16;
02717         if (lqi) {
02718             i = (16 - lqi);
02719         }
02720     }
02721     return i;
02722 }
02723 
02724 int protocol_6lowpan_del_ll16(protocol_interface_info_entry_t *cur, uint16_t mac_short_address)
02725 {
02726     uint8_t address[16];
02727     memcpy(address, ADDR_LINK_LOCAL_PREFIX, 8);
02728     memcpy(address + 8, ADDR_SHORT_ADR_SUFFIC, 6);
02729     common_write_16_bit(mac_short_address, &address[14]);
02730 
02731     return addr_delete(cur, address);
02732 }
02733 
02734 int protocol_6lowpan_set_ll16(protocol_interface_info_entry_t *cur, uint16_t mac_short_address)
02735 {
02736     if_address_entry_t *address_entry;
02737     uint8_t address[16];
02738     memcpy(address, ADDR_LINK_LOCAL_PREFIX, 8);
02739     memcpy(address + 8, ADDR_SHORT_ADR_SUFFIC , 6);
02740     common_write_16_bit(mac_short_address, &address[14]);
02741 
02742     address_entry = addr_add(cur, address, 64, ADDR_SOURCE_UNKNOWN, 0xffffffff, 0xffffffff, false);
02743     if (address_entry) {
02744         return 0;
02745     }
02746     return -1;
02747 }
02748 
02749 static void protocol_6lowpan_generate_link_reject(protocol_interface_info_entry_t *cur, const mlme_comm_status_t *status)
02750 {
02751     uint8_t address[16];
02752     memcpy(address, ADDR_LINK_LOCAL_PREFIX, 8);
02753     if (status->SrcAddrMode == MAC_ADDR_MODE_16_BIT) {
02754         memcpy(address + 8, ADDR_SHORT_ADR_SUFFIC , 6);
02755         memcpy(address + 14,status->SrcAddr, 2);
02756     } else {
02757         memcpy(address + 8,status->SrcAddr, 8);
02758         address[8] ^= 2;
02759     }
02760     if (mac_helper_default_security_level_get(cur)) {
02761         tr_debug("Drop link by asymmetric security");
02762         mle_service_reject_message_build(cur->id, address, false);
02763         return;
02764     }
02765 
02766 }
02767 
02768 static void lowpan_comm_status_indication_cb(int8_t if_id, const mlme_comm_status_t* status)
02769 {
02770     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(if_id);
02771     if (!cur) {
02772         return;
02773     }
02774 
02775     mac_neighbor_table_entry_t * entry_ptr;
02776 
02777     switch (status->status) {
02778         case MLME_UNSUPPORTED_SECURITY:
02779         case MLME_UNAVAILABLE_KEY:
02780             /* Generate MLE Link Reject to destination */
02781             if (status->DstAddrMode == MAC_ADDR_MODE_16_BIT && status->DstAddr[0] == 0xff && status->DstAddr[1] == 0xff) {
02782                 return; //Drop brodcast security failure
02783             }
02784 
02785             if (!cur->mle_link_reject_tokens) {
02786                 return;
02787             }
02788             cur->mle_link_reject_tokens--;
02789             protocol_6lowpan_generate_link_reject(cur, status);
02790 
02791             break;
02792         case MLME_DATA_POLL_NOTIFICATION:
02793             entry_ptr = mac_neighbor_table_address_discover(mac_neighbor_info(cur), status->SrcAddr, status->SrcAddrMode);
02794             if (entry_ptr) {
02795                 // Refresh Timeout
02796                 mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_ptr, entry_ptr->link_lifetime );
02797             }
02798             break;
02799         default:
02800             break;
02801     }
02802 }
02803 
02804 bool lowpan_neighbour_data_clean(int8_t interface_id, const uint8_t *link_local_address)
02805 {
02806 
02807     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
02808     if (!cur) {
02809         return false;
02810     }
02811     bool return_value = false;
02812     mac_neighbor_table_entry_t *neigh_entry = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), link_local_address, false, NULL);
02813     if (neigh_entry) {
02814         //Remove entry
02815         if (neigh_entry->link_role  == PRIORITY_PARENT_NEIGHBOUR || neigh_entry->link_role  == SECONDARY_PARENT_NEIGHBOUR) {
02816             return_value = true;
02817         }
02818         mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), neigh_entry);
02819     }
02820     return return_value;
02821 }
02822 
02823 void protocol_6lowpan_mle_timer(uint16_t ticks_update)
02824 {
02825 #ifndef NO_MLE
02826     if (mle_6lowpan_data) {
02827         /* Three request in burst and after that one link request per second */
02828         mle_6lowpan_data->link_req_token_bucket += ticks_update;
02829         if (mle_6lowpan_data->link_req_token_bucket > MLE_LINK_REQ_TOKEN_BUCKET_SIZE) {
02830             mle_6lowpan_data->link_req_token_bucket = MLE_LINK_REQ_TOKEN_BUCKET_SIZE;
02831         }
02832     }
02833 #endif
02834 }
02835 
02836 #endif