EL4121 Embedded System / mbed-os

Dependents:   cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more

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