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