Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more
thread_host_bootstrap.c
00001 /* 00002 * Copyright (c) 2015-2017, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: BSD-3-Clause 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the copyright holder nor the 00014 * names of its contributors may be used to endorse or promote products 00015 * derived from this software without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00018 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00021 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00022 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00023 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00024 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00025 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00026 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00027 * POSSIBILITY OF SUCH DAMAGE. 00028 */ 00029 00030 /* 00031 * \file thread_host_bootstrap.c 00032 * \brief Add short description about this file!!! 00033 * 00034 */ 00035 00036 #include "nsconfig.h" 00037 #ifdef HAVE_THREAD 00038 #include <string.h> 00039 #include <ns_types.h> 00040 #include <nsdynmemLIB.h> 00041 #include "eventOS_event.h" 00042 #include "eventOS_event_timer.h" 00043 #include "shalib.h" 00044 #include "common_functions.h" 00045 #include "NWK_INTERFACE/Include/protocol.h" 00046 #include "net_thread_test.h" 00047 #include "ns_trace.h" 00048 #include "6LoWPAN/Bootstraps/protocol_6lowpan.h" 00049 #include "6LoWPAN/Thread/thread_common.h" 00050 #include "6LoWPAN/Thread/thread_routing.h" 00051 #include "6LoWPAN/Thread/thread_nd.h" 00052 #include "6LoWPAN/Thread/thread_network_synch.h" 00053 #include "6LoWPAN/Thread/thread_bootstrap.h" 00054 #include "6LoWPAN/Thread/thread_host_bootstrap.h" 00055 #include "6LoWPAN/Thread/thread_router_bootstrap.h" 00056 #include "6LoWPAN/Thread/thread_leader_service.h" 00057 #include "6LoWPAN/Thread/thread_management_internal.h" 00058 #include "6LoWPAN/Thread/thread_network_synch.h" 00059 #include "6LoWPAN/Thread/thread_lowpower_private_api.h" 00060 #include "6LoWPAN/Thread/thread_extension.h" 00061 #include "6LoWPAN/Thread/thread_joiner_application.h" 00062 #include "6LoWPAN/Thread/thread_management_internal.h" 00063 #include "6LoWPAN/Thread/thread_management_client.h" 00064 #include "6LoWPAN/Thread/thread_network_data_lib.h" 00065 #include "6LoWPAN/Thread/thread_tmfcop_lib.h" 00066 #include "6LoWPAN/Thread/thread_nvm_store.h" 00067 #include "thread_management_if.h" 00068 #include "Common_Protocols/ipv6.h" 00069 #include "MPL/mpl.h" 00070 #include "MLE/mle_tlv.h" 00071 #include "thread_config.h" 00072 #include "Service_Libs/mle_service/mle_service_api.h" 00073 #include "Service_Libs/blacklist/blacklist.h" 00074 #include "6LoWPAN/MAC/mac_helper.h" 00075 #include "6LoWPAN/MAC/mac_data_poll.h" 00076 #include "Core/include/address.h" 00077 00078 #define TRACE_GROUP "tebs" 00079 00080 static bool thread_child_update_timeout_cb(int8_t interface_id, uint16_t msgId, bool usedAllRerties); 00081 static bool thread_parent_discover_timeout_cb(int8_t interface_id, uint16_t msgId, bool usedAllRetries); 00082 static bool thread_child_id_req_timeout(int8_t interface_id, uint16_t msgId, bool usedAllRetries); 00083 00084 static void thread_child_synch_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers); 00085 static void thread_mle_child_request_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers); 00086 00087 static int thread_parent_request_build(protocol_interface_info_entry_t *cur); 00088 00089 static int thread_attach_child_id_request_build(protocol_interface_info_entry_t *cur); 00090 static int thread_end_device_synch_response_validate(protocol_interface_info_entry_t *cur, uint8_t *ptr, uint16_t data_length, uint8_t linkMargin, uint8_t *src_address, mle_security_header_t *securityHeader); 00091 00092 static uint8_t *thread_single_address_registration_tlv_write(uint8_t *ptr, lowpan_context_t *ctx, uint8_t *addressPtr); 00093 static int8_t thread_end_device_synch_start(protocol_interface_info_entry_t *cur); 00094 00095 00096 void thread_child_set_default_route(protocol_interface_info_entry_t *cur) 00097 { 00098 thread_parent_info_t *parent = cur->thread_info->thread_endnode_parent; 00099 00100 if (!parent) { 00101 tr_debug("child default route set fail"); 00102 return; 00103 } 00104 cur->lowpan_info &= ~INTERFACE_NWK_ROUTER_DEVICE; 00105 uint8_t ula[16]; 00106 // SET Default route to ::/0 00107 memcpy(ula, ADDR_LINK_LOCAL_PREFIX, 8); 00108 memcpy(&ula[8], parent->mac64 , 8); 00109 ula[8] ^= 2; 00110 if (ipv6_route_add(NULL, 0, cur->id, ula, ROUTE_THREAD, 0xffffffff, 0) == NULL) { 00111 tr_error("fail to add default route"); 00112 } 00113 } 00114 00115 static void thread_network_data_clean(protocol_interface_info_entry_t *cur) 00116 { 00117 tr_debug("Clean network data"); 00118 thread_network_data_router_id_mark_delete(&cur->thread_info->networkDataStorage, 0xffff, false); 00119 thread_network_data_router_id_free(&cur->thread_info->networkDataStorage, false, cur); 00120 } 00121 00122 static void thread_merge_prepare(protocol_interface_info_entry_t *cur) 00123 { 00124 thread_clean_old_16_bit_address_based_addresses(cur); 00125 mpl_clear_realm_scope_seeds(cur); 00126 ipv6_neighbour_cache_flush(&cur->ipv6_neighbour_cache); 00127 ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_PROXIED_HOST, NULL); 00128 thread_routing_deactivate(&cur->thread_info->routing); 00129 thread_routing_init(&cur->thread_info->routing); 00130 cur->nwk_mode = ARM_NWK_GP_IP_MODE; 00131 thread_network_data_clean(cur); 00132 } 00133 00134 //This function is for Thread Parent scan callback 00135 static bool thread_parent_discover_timeout_cb(int8_t interface_id, uint16_t msgId, bool usedAllRetries) 00136 { 00137 protocol_interface_info_entry_t *cur; 00138 00139 cur = protocol_stack_interface_info_get_by_id(interface_id); 00140 if (!cur) { 00141 return false; 00142 } 00143 00144 cur->nwk_nd_re_scan_count++; 00145 00146 tr_debug("Parse parent scan result"); 00147 if (cur->thread_info->thread_attach_scanned_parent) { 00148 uint8_t ll64[16]; 00149 thread_scanned_parent_t *parent = cur->thread_info->thread_attach_scanned_parent; 00150 link_configuration_s *linkConfiguration; 00151 mle_neigh_table_entry_t *entry_temp; 00152 00153 linkConfiguration = thread_joiner_application_get_config(interface_id); 00154 if (!linkConfiguration) { 00155 return false; 00156 } 00157 00158 /* SED requires that scanned parent is added to MLE table */ 00159 memcpy(ll64, ADDR_LINK_LOCAL_PREFIX , 8); 00160 memcpy(&ll64[8], parent->mac64 , 8); 00161 ll64[8] ^= 2; 00162 00163 entry_temp = mle_class_get_entry_by_ll64(interface_id, parent->linkMarginToParent,ll64, true); 00164 if (entry_temp == NULL) { 00165 return false; 00166 } 00167 entry_temp->threadNeighbor = true; 00168 entry_temp->short_adr = parent->shortAddress; 00169 entry_temp->priorityFlag = true; 00170 entry_temp->holdTime = 90; 00171 entry_temp->mle_frame_counter = parent->mleFrameCounter; 00172 00173 thread_management_key_sets_calc(cur, linkConfiguration, cur->thread_info->thread_attach_scanned_parent->keySequence); 00174 thread_calculate_key_guard_timer(cur, linkConfiguration, true); 00175 00176 mac_helper_devicetable_set(entry_temp, cur, parent->linLayerFrameCounter, mac_helper_default_key_index_get(cur)); 00177 mle_entry_timeout_update(entry_temp, THREAD_DEFAULT_LINK_LIFETIME); 00178 00179 if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) { 00180 nwk_thread_host_control(cur, NET_HOST_FAST_POLL_MODE, 50); 00181 } 00182 00183 tr_debug("Parent found, send child ID req"); 00184 thread_attach_child_id_request_build(cur); 00185 return false; 00186 00187 } else { 00188 uint8_t *dataPtr; 00189 uint16_t dataLength; 00190 00191 if (usedAllRetries) { 00192 if (thread_is_connected(cur)) { 00193 // Did not find any better partition to join. Be happy. 00194 cur->nwk_bootstrap_state = ER_MLE_ATTACH_READY; 00195 return true; 00196 } 00197 // Trig new state which call this 00198 thread_bootstrap_connection_error(cur->id, CON_ERROR_NETWORK_ATTACH_FAIL, NULL); 00199 return false; 00200 } 00201 00202 //GET Data pointer 00203 dataPtr = mle_service_get_payload_start_point(msgId); 00204 dataLength = mle_service_get_payload_length(msgId); 00205 00206 if (dataPtr) { 00207 mle_tlv_info_t tlv_info; 00208 //Scan MLE_TYPE_SCAN_MASK 00209 if (mle_tlv_option_discover(dataPtr, dataLength, MLE_TYPE_SCAN_MASK, &tlv_info)) { 00210 dataPtr = tlv_info.dataPtr; 00211 *dataPtr |= 0x40; //ADD REED Bit 00212 } 00213 } 00214 } 00215 return true; 00216 } 00217 00218 static int thread_parent_request_build(protocol_interface_info_entry_t *cur) 00219 { 00220 uint8_t *ptr; 00221 uint8_t mode; 00222 mle_message_timeout_params_t timeout; 00223 uint32_t keySequence; 00224 uint8_t scanMask = 0x80; 00225 00226 mle_service_interface_tx_queue_clean(cur->id); 00227 00228 uint16_t buf_id = mle_service_msg_allocate(cur->id, 32, true, MLE_COMMAND_PARENT_REQUEST); 00229 if (buf_id == 0) { 00230 return -1; 00231 } 00232 00233 if (cur->thread_info->thread_attached_state == THREAD_STATE_REATTACH || 00234 cur->thread_info->thread_attached_state == THREAD_STATE_REATTACH_RETRY) { 00235 // When doing re-attach End devices are immediately accepted as parents 00236 scanMask |= 0x40; 00237 } 00238 thread_management_get_current_keysequence(cur->id, &keySequence); 00239 mle_service_msg_update_security_params(buf_id, 5, 2, keySequence); 00240 00241 //SET Multicast to all Router ff02::2 00242 mle_service_set_msg_destination_address(buf_id, ADDR_LINK_LOCAL_ALL_ROUTERS); 00243 tr_debug("Thread parent request"); 00244 00245 ptr = mle_service_get_data_pointer(buf_id); 00246 ptr = mle_tlv_write_scan_mask(ptr, scanMask); 00247 ptr = mle_tlv_write_version(ptr, cur->thread_info->version); 00248 mode = thread_mode_get_by_interface_ptr(cur); 00249 00250 /* If we are a SLEEPY host, we do NOT set RX_ON_IDLE bit in parent requests */ 00251 /* NOTE: the RX_ON_IDLE is temporarily set on the interface during bootstrap */ 00252 if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) { 00253 mode &= ~MLE_RX_ON_IDLE; 00254 } 00255 00256 ptr = mle_tlv_write_mode(ptr, mode); 00257 if (mle_service_update_length_by_ptr(buf_id,ptr)!= 0) { 00258 tr_debug("Buffer overflow at message write"); 00259 } 00260 timeout.retrans_max = THREAD_PARENT_REQUEST_MAX_RETRY_CNT; 00261 timeout.timeout_init = 1; 00262 timeout.timeout_max = 2; 00263 timeout.delay = MLE_NO_DELAY; 00264 cur->nwk_nd_re_scan_count = 1; 00265 mle_service_set_packet_callback(buf_id, thread_parent_discover_timeout_cb); 00266 if (cur->thread_info->thread_attached_state == THREAD_STATE_NETWORK_DISCOVER) { 00267 mle_service_interface_receiver_handler_update(cur->id, thread_mle_parent_discover_receive_cb); 00268 } else { 00269 mle_service_interface_receiver_handler_update(cur->id, thread_general_mle_receive_cb); 00270 } 00271 00272 mle_service_set_msg_timeout_parameters(buf_id, &timeout); 00273 mle_service_send_message(buf_id); 00274 return 0; 00275 } 00276 00277 void thread_network_attach_start(protocol_interface_info_entry_t *cur) 00278 { 00279 if (thread_parent_request_build(cur) == 0) { 00280 tr_debug("MLE Parent request"); 00281 cur->nwk_bootstrap_state = ER_MLE_SCAN; 00282 cur->bootsrap_state_machine_cnt = 0; 00283 } else { 00284 cur->bootsrap_state_machine_cnt = 5; 00285 } 00286 } 00287 00288 static int thread_end_device_synch_response_validate(protocol_interface_info_entry_t *cur, uint8_t *ptr, uint16_t data_length, uint8_t linkMargin, uint8_t *src_address, mle_security_header_t *securityHeader) 00289 { 00290 uint8_t shortAddress[2]; 00291 uint8_t status, mode; 00292 uint16_t srcAddress; 00293 uint16_t address16; 00294 uint32_t llFrameCounter; 00295 thread_leader_data_t leaderData; 00296 mle_neigh_table_entry_t *entry_temp; 00297 00298 tr_debug("Validate Link Synch Response"); 00299 //Check First Status 00300 if (mle_tlv_read_8_bit_tlv(MLE_TYPE_STATUS, ptr, data_length, &status)) { 00301 tr_debug("Synch status response %x",status); 00302 //Clean synch state and start 00303 return -1; 00304 } 00305 // Validate response 00306 // MLE_TYPE_MODE 00307 // Address 00308 // MLE_TYPE_SRC_ADDRESS 00309 // MLE_TYPE_LEADER_DATA 00310 if (!mle_tlv_read_8_bit_tlv(MLE_TYPE_MODE, ptr, data_length, &mode) || 00311 !mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, ptr, data_length, &srcAddress) || 00312 !mle_tlv_read_16_bit_tlv(MLE_TYPE_ADDRESS16, ptr, data_length, &address16) || 00313 !thread_leader_data_parse(ptr, data_length, &leaderData) || 00314 !mle_tlv_read_32_bit_tlv(MLE_TYPE_LL_FRAME_COUNTER, ptr, data_length, &llFrameCounter)) { 00315 tr_debug("missing TLV's"); 00316 return -1; 00317 } 00318 00319 if (securityHeader->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) { 00320 thread_management_key_synch_req(cur->id, common_read_32_bit(securityHeader->Keysource)); 00321 } else { 00322 tr_debug("Key ID Mode 2 not used; dropped."); 00323 return -3; 00324 } 00325 00326 //Update parent link information 00327 entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, src_address, true); 00328 00329 if (!entry_temp) { 00330 tr_debug("Neighbor allocate fail"); 00331 return -2; 00332 } 00333 /* 00334 00335 */ 00336 entry_temp->threadNeighbor = true; 00337 entry_temp->short_adr = srcAddress; 00338 entry_temp->handshakeReady = 1; 00339 entry_temp->holdTime = 90; 00340 entry_temp->priorityFlag = true; // Make this our parent 00341 common_write_16_bit(entry_temp->short_adr, shortAddress); 00342 00343 mac_helper_coordinator_address_set(cur, ADDR_802_15_4_SHORT , shortAddress); 00344 mle_entry_timeout_update(entry_temp, thread_info(cur)->host_link_timeout); 00345 mac_helper_devicetable_set(entry_temp, cur, llFrameCounter, securityHeader->KeyIndex); 00346 00347 thread_info(cur)->thread_attached_state = THREAD_STATE_CONNECTED; 00348 thread_bootstrap_update_ml16_address(cur, address16); 00349 //SET Parent Info and free scan response info 00350 thread_info(cur)->thread_endnode_parent->shortAddress = srcAddress; 00351 thread_info(cur)->thread_endnode_parent->router_id = srcAddress >> 10; 00352 memcpy(thread_info(cur)->thread_endnode_parent->mac64, entry_temp->mac64, 8); 00353 00354 mle_tlv_info_t routing; 00355 if (mle_tlv_read_tlv(MLE_TYPE_ROUTE, ptr, data_length, &routing)) { 00356 thread_router_bootstrap_route_tlv_push(cur, routing.dataPtr, routing.tlvLen, linkMargin, entry_temp); 00357 } 00358 00359 //Copy Leader Data 00360 *thread_info(cur)->thread_leader_data = leaderData; 00361 00362 /*save the data version to one less than what was received so that any inconsistencies in network data is 00363 * fixed by a data request to parent 00364 */ 00365 thread_info(cur)->thread_leader_data->stableDataVersion = leaderData.stableDataVersion - 1; 00366 thread_info(cur)->thread_leader_data->dataVersion = leaderData.dataVersion - 1; 00367 00368 00369 return 0; 00370 00371 } 00372 00373 static void thread_child_synch_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers) 00374 { 00375 tr_debug("Thread MLE message child_synch handler"); 00376 //State machine What packet shuold accept in this case 00377 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 00378 if (!cur) { 00379 return; 00380 } 00381 00382 /* Check that message is from link-local scope */ 00383 if(!addr_is_ipv6_link_local(mle_msg->packet_src_address)) { 00384 return; 00385 } 00386 00387 uint16_t messageId; 00388 uint8_t linkMargin = thread_compute_link_margin(mle_msg->dbm); 00389 //State machine What packet shuold accept in this case 00390 switch (mle_msg->message_type) { 00391 case MLE_COMMAND_CHILD_UPDATE_RESPONSE: 00392 00393 messageId = mle_tlv_validate_response(mle_msg->data_ptr, mle_msg->data_length); 00394 00395 if (messageId == 0) { 00396 tr_debug("Not for me"); 00397 return; 00398 } 00399 00400 if (thread_end_device_synch_response_validate(cur, mle_msg->data_ptr, mle_msg->data_length, linkMargin, mle_msg->packet_src_address, security_headers) != 0) { 00401 tr_warn("End device synch failed"); 00402 mle_service_msg_free(messageId); 00403 thread_bootsrap_device_synch_fail(cur); 00404 return; 00405 } 00406 mle_tlv_info_t networkDataTlv; 00407 thread_leader_data_t leaderData; 00408 tr_debug("End device synch Possible"); 00409 00410 cur->thread_info->thread_attached_state = THREAD_STATE_CONNECTED; 00411 00412 if (mle_tlv_read_tlv(MLE_TYPE_NETWORK_DATA, mle_msg->data_ptr, mle_msg->data_length, &networkDataTlv) && 00413 thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData)) { 00414 thread_bootstrap_network_data_save(cur, &leaderData, networkDataTlv.dataPtr, networkDataTlv.tlvLen); 00415 } else { 00416 thread_bootstrap_parent_network_data_request(cur, true); 00417 } 00418 thread_bootstrap_attached_ready(cur); 00419 00420 //SET For sleepy state and mode update 00421 if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) { 00422 nwk_thread_host_control(cur, NET_HOST_FAST_POLL_MODE, 1); 00423 //TRIG Child Update state 00424 thread_bootstrap_child_update_trig(cur); 00425 } 00426 00427 mle_service_msg_free(messageId); 00428 break; 00429 } 00430 } 00431 00432 static bool thread_host_prefer_parent_response(protocol_interface_info_entry_t *cur, thread_scanned_parent_t *scanned_parent, uint16_t version, thread_connectivity_t *connectivity) 00433 { 00434 (void) connectivity; 00435 (void) cur; 00436 00437 if (!thread_extension_version_check(thread_info(cur)->version)) { 00438 return false; 00439 } 00440 00441 if (version < scanned_parent->version) { 00442 tr_debug("prefer existing parent response from %"PRIX16, scanned_parent->shortAddress); 00443 return true; 00444 } 00445 00446 return false; 00447 } 00448 00449 /* MLE callback for parent response messages. 00450 * 00451 * The Parent Response contains these TLVs: 00452 * - Source Address TLV 00453 * - Leader Data TLV 00454 * - Link-layer Frame Counter TLV 00455 * - MLE Frame Counter TLV (optional) 00456 * - Response TLV 00457 * - Challenge TLV 00458 * - Link Margin TLV 00459 * - Connectivity TLV 00460 * - Version TLV 00461 */ 00462 void thread_mle_parent_discover_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers) 00463 { 00464 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 00465 if (!cur) { 00466 return; 00467 } 00468 00469 /* Check that message is from link-local scope */ 00470 if(!addr_is_ipv6_link_local(mle_msg->packet_src_address)) { 00471 return; 00472 } 00473 00474 tr_debug("Thread MLE Parent request response Handler"); 00475 //State machine What packet should accept in this case 00476 switch (mle_msg->message_type) { 00477 case MLE_COMMAND_PARENT_RESPONSE: { 00478 thread_scanned_parent_t *scan_result = NULL; 00479 uint16_t messageId; 00480 uint16_t srcAddress, version; 00481 uint32_t llFrameCounter; 00482 uint32_t mleFrameCounter; 00483 uint8_t rssiValue; 00484 mle_tlv_info_t challengeTlv; 00485 uint8_t currentMargin, newMargin; 00486 thread_link_quality_e newLqi; 00487 thread_leader_data_t leaderData; 00488 thread_connectivity_t connectivityTlv; 00489 bool accept_response; 00490 00491 tr_info("Parent Response"); 00492 if (security_headers->KeyIdMode != MAC_KEY_ID_MODE_SRC4_IDX) { 00493 tr_debug("Wrong key mode %u ", security_headers->KeyIdMode); 00494 return; 00495 } 00496 messageId = mle_tlv_validate_response(mle_msg->data_ptr, mle_msg->data_length); 00497 00498 if (messageId == 0) { 00499 tr_debug("Not for me"); 00500 return; 00501 } 00502 00503 //Read Leader Data and verify connectivity 00504 if (!thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData)) { 00505 return; 00506 } 00507 if (!mle_tlv_read_8_bit_tlv(MLE_TYPE_RSSI, mle_msg->data_ptr, mle_msg->data_length, &rssiValue)) { 00508 return; 00509 } 00510 if (!thread_connectivity_tlv_parse(mle_msg->data_ptr, mle_msg->data_length, &connectivityTlv)) { 00511 return; 00512 } 00513 if (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, mle_msg->data_ptr, mle_msg->data_length, &srcAddress)) { 00514 return; 00515 } 00516 if (!mle_tlv_read_16_bit_tlv(MLE_TYPE_VERSION, mle_msg->data_ptr, mle_msg->data_length, &version)) { 00517 return; 00518 } 00519 if (!mle_tlv_read_32_bit_tlv(MLE_TYPE_LL_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &llFrameCounter)) { 00520 return; 00521 } 00522 if (!mle_tlv_read_tlv(MLE_TYPE_CHALLENGE, mle_msg->data_ptr, mle_msg->data_length, &challengeTlv)) { 00523 return; 00524 } 00525 //If MLE MLE_TYPE_MLE_FRAME_COUNTER TLV is present then use it for validating further messages else use link layer frame counter 00526 if (!mle_tlv_read_32_bit_tlv(MLE_TYPE_MLE_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &mleFrameCounter)) { 00527 mleFrameCounter = llFrameCounter; 00528 } 00529 00530 /** 00531 * At THREAD_STATE_REATTACH state only accept same Partition ID and Higher ID than current 00532 */ 00533 if (thread_info(cur)->thread_attached_state == THREAD_STATE_REATTACH || thread_info(cur)->thread_attached_state == THREAD_STATE_REATTACH_RETRY) { 00534 tr_debug("Reattach"); 00535 if (thread_info(cur)->thread_leader_data) { 00536 if (thread_info(cur)->thread_leader_data->partitionId != leaderData.partitionId) { //accept only same ID at reattach phase 00537 return; 00538 } 00539 //Compare ID - when downgrading, accept all 00540 if (!thread_info(cur)->releaseRouterId) { 00541 if (!common_serial_number_greater_8(connectivityTlv.idSequence, thread_info(cur)->routing.router_id_sequence)) { 00542 tr_debug("Drop old partition by old ID"); 00543 return; 00544 } else { 00545 tr_debug("Accept old partition by new ID"); 00546 } 00547 } 00548 } 00549 } else if (thread_info(cur)->thread_attached_state == THREAD_STATE_ATTACH_ANY || 00550 thread_info(cur)->thread_attached_state == THREAD_STATE_CONNECTED || 00551 thread_info(cur)->thread_attached_state == THREAD_STATE_CONNECTED_ROUTER) { 00552 if (thread_info(cur)->thread_leader_data) { 00553 if (thread_info(cur)->thread_leader_data->partitionId == leaderData.partitionId) { //accept only different ID at anyattach phase 00554 tr_debug("Drop old partition"); 00555 return; 00556 } 00557 } else { 00558 //TODO Fix this 00559 tr_error("No leader Data allocated for AnyAttach,Why?"); 00560 } 00561 } 00562 00563 if (blacklist_reject(mle_msg->packet_src_address)) { 00564 tr_debug("Drop Parent Response because blacklisted"); 00565 return; 00566 } 00567 00568 /* Calculate this parent link margin */ 00569 newMargin = thread_calculate_link_margin(mle_msg->dbm, rssiValue); 00570 newLqi = thread_link_margin_to_quality(newMargin << THREAD_LINK_MARGIN_SCALING); 00571 tr_debug("Parent scan count %d addr:%04x Margin:%d lqi:%d", cur->nwk_nd_re_scan_count, srcAddress, newMargin, newLqi); 00572 if (newLqi == QUALITY_BAD) { 00573 tr_debug("Drop Bad Link"); 00574 accept_response = false; 00575 } else { 00576 if (cur->nwk_nd_re_scan_count <= 1) { 00577 if (newLqi == QUALITY_20dB) { 00578 accept_response = true; 00579 } else { 00580 tr_debug("Drop first time less than QUALITY_20dB"); 00581 accept_response = false; 00582 } 00583 } else { 00584 accept_response = true; 00585 } 00586 } 00587 00588 00589 if (accept_response) { 00590 if (thread_info(cur)->thread_attach_scanned_parent == NULL) { 00591 thread_info(cur)->thread_attach_scanned_parent = ns_dyn_mem_temporary_alloc(sizeof(thread_scanned_parent_t)); 00592 if (!thread_info(cur)->thread_attach_scanned_parent) { 00593 return; 00594 } 00595 thread_info(cur)->thread_attach_scanned_parent->child_id_request_id = 0; 00596 scan_result = thread_info(cur)->thread_attach_scanned_parent; 00597 tr_debug("Partition %"PRIu32, leaderData.partitionId); 00598 } else { 00599 uint32_t currentPartitionId = thread_info(cur)->thread_attach_scanned_parent->leader_data.partitionId; 00600 tr_debug("Current %"PRIu32" RX %"PRIu32, currentPartitionId, leaderData.partitionId); 00601 00602 if (leaderData.partitionId != currentPartitionId) { 00603 int retVal = thread_bootstrap_partition_process(cur, connectivityTlv.activeRouters, &leaderData,NULL); 00604 if (retVal > 0) 00605 scan_result = thread_info(cur)->thread_attach_scanned_parent; 00606 } 00607 else if (leaderData.partitionId == currentPartitionId) { 00608 thread_link_quality_e currentLqi; 00609 //Calculate Current summed LQI 00610 scan_result = thread_info(cur)->thread_attach_scanned_parent; 00611 currentMargin = thread_parent_margin_calc(scan_result->linkMarginFromParent, scan_result->linkMarginToParent); 00612 currentLqi = thread_link_margin_to_quality(currentMargin << THREAD_LINK_MARGIN_SCALING); 00613 tr_debug("Compare LQI from margins:"); 00614 tr_debug("New Margin %d vs Cur %d", newMargin, currentMargin); 00615 tr_debug("New Lqi %d vs Cur %d", newLqi, currentLqi); 00616 if (newLqi > currentLqi) { 00617 /*Override old parent data*/ 00618 tr_debug("Better Parent Lqi"); 00619 } else { 00620 if (newLqi == currentLqi) { 00621 //Compare if REED 00622 if (thread_is_router_addr(scan_result->shortAddress) && 00623 !thread_is_router_addr(srcAddress) ) { 00624 scan_result = NULL; 00625 tr_debug("Dropped Response from REED over router"); 00626 } else if (connectivityTlv.parentPriority > scan_result->parentPriority) { 00627 tr_debug("Better parent priority %d>%d", connectivityTlv.parentPriority, scan_result->parentPriority); 00628 } else if (connectivityTlv.parentPriority < scan_result->parentPriority) { 00629 tr_debug("Dropped Response - lower parent priority %d<%d", connectivityTlv.parentPriority, scan_result->parentPriority); 00630 scan_result = NULL; 00631 } else { 00632 tr_debug("Similar LQI check connectivity old: %d,%d,%d new:%d,%d,%d", 00633 scan_result->linkQuality3, scan_result->linkQuality2, scan_result->linkQuality1, 00634 connectivityTlv.linkQuality3, connectivityTlv.linkQuality2, connectivityTlv.linkQuality1); 00635 00636 if (scan_result->linkQuality3 > connectivityTlv.linkQuality3) { 00637 scan_result = NULL; 00638 } 00639 if (scan_result && 00640 scan_result->linkQuality3 == connectivityTlv.linkQuality3 && 00641 scan_result->linkQuality2 > connectivityTlv.linkQuality2) { 00642 scan_result = NULL; 00643 } 00644 if (scan_result && 00645 scan_result->linkQuality3 == connectivityTlv.linkQuality3 && 00646 scan_result->linkQuality2 == connectivityTlv.linkQuality2 && 00647 scan_result->linkQuality1 > connectivityTlv.linkQuality1) { 00648 scan_result = NULL; 00649 } 00650 if(!scan_result) { 00651 tr_debug("Dropped Connectivity is not as good"); 00652 } 00653 } 00654 } else { 00655 scan_result = NULL; 00656 } 00657 } 00658 } 00659 if (scan_result && thread_host_prefer_parent_response(cur, scan_result, version, &connectivityTlv)){ 00660 scan_result = NULL; 00661 } 00662 00663 } 00664 } 00665 00666 if (scan_result) { 00667 // save the result 00668 thread_leader_data_t *leader; 00669 scan_result->linkMarginToParent = thread_compute_link_margin(mle_msg->dbm); 00670 scan_result->linkMarginFromParent = rssiValue; 00671 scan_result->linLayerFrameCounter = llFrameCounter; 00672 scan_result->mleFrameCounter = mleFrameCounter; 00673 scan_result->shortAddress = srcAddress; 00674 scan_result->version = version; 00675 memcpy(scan_result->challengeData, challengeTlv.dataPtr, challengeTlv.tlvLen); 00676 scan_result->chal_len = challengeTlv.tlvLen; 00677 //Save MAC address from LL64 00678 memcpy(scan_result->mac64, (mle_msg->packet_src_address + 8), 8); 00679 scan_result->mac64[0] ^= 2; 00680 leader = &scan_result->leader_data; 00681 //Copy Leader Data 00682 *leader = leaderData; 00683 scan_result->routeCostToLeader = connectivityTlv.leaderCost; 00684 scan_result->linkQuality3 = connectivityTlv.linkQuality3; 00685 scan_result->linkQuality2 = connectivityTlv.linkQuality2; 00686 scan_result->linkQuality1 = connectivityTlv.linkQuality1; 00687 scan_result->parentPriority = connectivityTlv.parentPriority; 00688 scan_result->activeRouters = connectivityTlv.activeRouters; 00689 scan_result->security_key_index = security_headers->KeyIndex; 00690 00691 thread_routing_update_link_margin(cur, scan_result->shortAddress, scan_result->linkMarginToParent, scan_result->linkMarginFromParent); 00692 scan_result->keySequence = common_read_32_bit(security_headers->Keysource); 00693 tr_debug("Current %"PRIu32" RX %"PRIu32" Cnt%"PRIu32, scan_result->leader_data.partitionId, leaderData.partitionId, scan_result->linLayerFrameCounter); 00694 } 00695 break; 00696 } 00697 default: 00698 break; 00699 } 00700 00701 } 00702 00703 /* Callback for child ID request. 00704 * 00705 * Child ID Response contains these TLVs: 00706 * - Source Address TLV 00707 * - Leader Data TLV 00708 * - Address16 TLV 00709 * - Network Data TLV (optional) 00710 * - Route64 TLV (optional) 00711 * - Address Registration TLV (optional) 00712 * - Active Operational Dataset TLV (optional) 00713 * - Pending Operational Dataset TLV (optional) 00714 */ 00715 static void thread_mle_child_request_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers) 00716 { 00717 thread_leader_data_t leaderData; 00718 mle_neigh_table_entry_t *entry_temp; 00719 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 00720 link_configuration_s *link_configuration; 00721 if (!cur) { 00722 return; 00723 } 00724 link_configuration = thread_joiner_application_get_config(cur->id); 00725 if (!link_configuration) { 00726 return; 00727 } 00728 00729 /* Check that message is from link-local scope */ 00730 if(!addr_is_ipv6_link_local(mle_msg->packet_src_address)) { 00731 return; 00732 } 00733 00734 tr_debug("Thread MLE Child request response Handler"); 00735 00736 switch (mle_msg->message_type) { 00737 00738 case MLE_COMMAND_CHILD_ID_RESPONSE: { 00739 uint8_t shortAddress[2]; 00740 uint16_t childId; 00741 mle_tlv_info_t routeTlv, addressRegisteredTlv, networkDataTlv; 00742 mle_tlv_info_t ConfigurationTlv; 00743 uint64_t pending_timestamp = 0; 00744 uint64_t active_timestamp; 00745 thread_scanned_parent_t *scan_result = thread_info(cur)->thread_attach_scanned_parent; 00746 00747 tr_info("Received Child ID Response"); 00748 00749 // Clear old data 00750 if (cur->thread_info->releaseRouterId) { 00751 thread_bootstrap_clear_neighbor_entries(cur); 00752 cur->thread_info->localServerDataBase.release_old_address = true; 00753 } 00754 00755 thread_clean_all_routers_from_neighbor_list(cur->id); 00756 thread_leader_service_stop(interface_id); 00757 thread_leader_service_leader_data_free(cur->thread_info); 00758 thread_merge_prepare(cur); 00759 00760 // Create entry for new parent 00761 entry_temp = mle_class_get_entry_by_ll64(cur->id, thread_compute_link_margin(mle_msg->dbm), mle_msg->packet_src_address, true); 00762 if (entry_temp == NULL) { 00763 // todo: what to do here? 00764 return; 00765 } 00766 00767 //Parse mandatory TLV's 00768 if (!thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData)) { 00769 return; 00770 } 00771 if (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, mle_msg->data_ptr, mle_msg->data_length, &entry_temp->short_adr)) { 00772 return; 00773 } 00774 00775 if (!mle_tlv_read_16_bit_tlv(MLE_TYPE_ADDRESS16, mle_msg->data_ptr, mle_msg->data_length, &childId)) { 00776 return; 00777 } 00778 00779 //Read Optional TLV's 00780 mle_tlv_read_tlv(MLE_TYPE_ADDRESS_REGISTRATION, mle_msg->data_ptr, mle_msg->data_length, &addressRegisteredTlv); 00781 mle_tlv_read_tlv(MLE_TYPE_NETWORK_DATA, mle_msg->data_ptr, mle_msg->data_length, &networkDataTlv); 00782 mle_tlv_read_tlv(MLE_TYPE_ROUTE, mle_msg->data_ptr, mle_msg->data_length, &routeTlv); 00783 // update operational datasets 00784 mle_tlv_read_tlv(MLE_TYPE_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv); 00785 if (mle_tlv_read_64_bit_tlv(MLE_TYPE_ACTIVE_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &active_timestamp)) { 00786 thread_active_operational_dataset_process(cur, ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen, active_timestamp); 00787 } 00788 // TODO check if result is true then need to update all configurations 00789 mle_tlv_read_tlv(MLE_TYPE_PENDING_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv); 00790 if (mle_tlv_read_64_bit_tlv(MLE_TYPE_PENDING_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &pending_timestamp)) { 00791 thread_pending_operational_dataset_process(cur, pending_timestamp, ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen); 00792 } else if (pending_timestamp < thread_joiner_application_pending_config_timestamp_get(cur->id)) { 00793 // parent did not have timestamp but we haver 00794 tr_info("save pending set for leader"); 00795 thread_joiner_application_next_pending_config_save(cur->id); 00796 thread_joiner_application_pending_config_delete(cur->id); 00797 } 00798 00799 *thread_info(cur)->thread_leader_data = leaderData; 00800 00801 thread_parent_info_t *parent = thread_parent_data_allocate(cur->thread_info); 00802 if (!parent) { 00803 tr_debug("Parent allocate fail."); 00804 return; 00805 } 00806 00807 common_write_16_bit(entry_temp->short_adr, shortAddress); 00808 //Update possible reed address by real router address 00809 scan_result->shortAddress = entry_temp->short_adr; 00810 00811 entry_temp->holdTime = 90; 00812 entry_temp->handshakeReady = 1; 00813 entry_temp->priorityFlag = true; 00814 entry_temp->threadNeighbor = true; 00815 00816 mac_helper_coordinator_address_set(cur, ADDR_802_15_4_SHORT , shortAddress); 00817 mle_entry_timeout_update(entry_temp, thread_info(cur)->host_link_timeout); 00818 mac_helper_devicetable_set(entry_temp, cur, scan_result->linLayerFrameCounter, security_headers->KeyIndex); 00819 00820 thread_info(cur)->thread_attached_state = THREAD_STATE_CONNECTED; 00821 00822 thread_bootstrap_update_ml16_address(cur, childId); 00823 00824 mle_service_msg_free(scan_result->child_id_request_id); 00825 00826 scan_result->child_id_request_id = 0; 00827 //SET Parent Info and free scan response info 00828 parent->pathCostToLeader = thread_sum_rx_path_cost_and_link_cost(scan_result->linkMarginToParent, scan_result->linkMarginFromParent, scan_result->routeCostToLeader); 00829 parent->shortAddress = scan_result->shortAddress; 00830 parent->router_id = (scan_result->shortAddress >> 10); 00831 memcpy(parent->mac64, scan_result->mac64, 8); 00832 //Check Network Data TLV 00833 if (networkDataTlv.tlvType == MLE_TYPE_NETWORK_DATA) { 00834 thread_bootstrap_network_data_save(cur, &leaderData, networkDataTlv.dataPtr, networkDataTlv.tlvLen); 00835 } else { 00836 cur->thread_info->thread_leader_data->dataVersion--; 00837 cur->thread_info->thread_leader_data->stableDataVersion--; 00838 } 00839 00840 blacklist_update(mle_msg->packet_src_address, true); 00841 00842 // 00843 if (routeTlv.tlvType == MLE_TYPE_ROUTE && routeTlv.tlvLen) { 00844 thread_router_bootstrap_route_tlv_push(cur, routeTlv.dataPtr, routeTlv.tlvLen , thread_compute_link_margin(mle_msg->dbm), entry_temp); 00845 } 00846 thread_bootstrap_attached_ready(cur); 00847 00848 break; 00849 } 00850 default: 00851 tr_debug("Unsupported TLV %d", mle_msg->message_type); 00852 break; 00853 00854 } 00855 } 00856 00857 static int8_t thread_end_device_synch_start(protocol_interface_info_entry_t *cur) 00858 { 00859 mle_message_timeout_params_t timeout; 00860 uint32_t keySequence; 00861 uint16_t buf_id = mle_service_msg_allocate(cur->id, 150 + 3 + 6 + 10, true,MLE_COMMAND_CHILD_UPDATE_REQUEST); 00862 if (buf_id == 0) { 00863 return -1; 00864 } 00865 uint8_t tlv_req[3]; 00866 00867 thread_management_get_current_keysequence(cur->id, &keySequence); 00868 mle_service_msg_update_security_params(buf_id, 5, 2, keySequence); 00869 uint8_t *address_ptr = mle_service_get_msg_destination_address_pointer(buf_id); 00870 //Set Parent Address 00871 memcpy(address_ptr, ADDR_LINK_LOCAL_PREFIX, 8); 00872 address_ptr += 8; 00873 memcpy(address_ptr, cur->thread_info->thread_endnode_parent->mac64, 8); 00874 *address_ptr ^= 2; 00875 uint8_t *ptr = mle_service_get_data_pointer(buf_id); 00876 //Add mode 00877 ptr = mle_tlv_write_mode(ptr, thread_mode_get_by_interface_ptr(cur)); 00878 ptr = thread_address_registration_tlv_write(ptr, cur); 00879 tlv_req[0] = MLE_TYPE_ADDRESS16; 00880 tlv_req[1] = MLE_TYPE_NETWORK_DATA; 00881 00882 if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) { 00883 // REEDs request Route64 as well 00884 tlv_req[2] = MLE_TYPE_ROUTE; 00885 ptr = mle_tlv_req_tlv(ptr, tlv_req, 3); 00886 } else { 00887 ptr = mle_tlv_req_tlv(ptr, tlv_req, 2); 00888 } 00889 00890 if (mle_service_update_length_by_ptr(buf_id,ptr)!= 0) { 00891 tr_debug("Buffer overflow at message write"); 00892 } 00893 00894 tr_debug("Send MLE Child Update Request (Child synchronisation)"); 00895 timeout.retrans_max = THREAD_REQUEST_MAX_RETRY_CNT; 00896 timeout.timeout_init = 1; 00897 timeout.timeout_max = 3; 00898 timeout.delay = MLE_NO_DELAY; 00899 00900 mle_service_set_packet_callback(buf_id, thread_device_synch_timeout); 00901 mle_service_set_msg_timeout_parameters(buf_id, &timeout); 00902 mle_service_send_message(buf_id); 00903 return 0; 00904 } 00905 00906 void thread_endevice_synch_start(protocol_interface_info_entry_t *cur) 00907 { 00908 if (cur->thread_info->thread_endnode_parent) { 00909 mle_neigh_table_entry_t *entry_temp; 00910 00911 // Add the parent to the MLE neighbor table 00912 entry_temp = mle_class_get_entry_by_mac64(cur->id, 64, cur->thread_info->thread_endnode_parent->mac64, true); 00913 00914 if (entry_temp) { 00915 entry_temp->short_adr = cur->thread_info->thread_endnode_parent->shortAddress; 00916 entry_temp->handshakeReady = 1; 00917 entry_temp->threadNeighbor = true; 00918 00919 // In case we don't get response to sync; use temporary timeout here, 00920 // Child ID Response handler will set correct value later 00921 mle_entry_timeout_update(entry_temp, 20); 00922 00923 // Add the parent to the MAC table (for e.g. secured/fragmented Child Update Response) 00924 mac_helper_devicetable_set(entry_temp, cur, 0, cur->mac_parameters->mac_default_key_index); 00925 } 00926 } 00927 00928 //Send Child Synch 00929 if (thread_end_device_synch_start(cur) == 0) { 00930 //SET Child synch receiver handler 00931 mle_service_interface_receiver_handler_update(cur->id, thread_child_synch_receive_cb); 00932 cur->nwk_bootstrap_state = ER_MLE_SYNCH; 00933 } 00934 } 00935 00936 static bool thread_child_id_req_timeout(int8_t interface_id, uint16_t msgId, bool usedAllRetries) 00937 { 00938 mle_neigh_table_entry_t *entry_temp; 00939 thread_scanned_parent_t *scanned_parent; 00940 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 00941 uint8_t ll64[16]; 00942 00943 (void)msgId; 00944 00945 if (!cur) { 00946 return false; 00947 } 00948 00949 // Not last retry - keep trying 00950 if (!usedAllRetries) { 00951 return true; 00952 } 00953 00954 //Do not release message inside this call MLE service will do that. 00955 cur->thread_info->thread_attach_scanned_parent->child_id_request_id = 0; 00956 00957 uint8_t *addr = mle_service_get_msg_destination_address_pointer(msgId); 00958 tr_debug("Child ID Request timed out, address: %s", trace_ipv6(addr)); 00959 00960 blacklist_update(addr, false); 00961 00962 scanned_parent = cur->thread_info->thread_attach_scanned_parent; 00963 00964 /* Used all retries - if we are on any attach state or */ 00965 /* if we don't have route to leader, start any-attach */ 00966 if (thread_info(cur)->thread_attached_state == THREAD_STATE_NETWORK_DISCOVER || 00967 -1 == thread_route_ready_to_leader(cur) || !scanned_parent) { 00968 tr_debug("start any-attach"); 00969 thread_bootstrap_connection_error(interface_id, CON_ERROR_NETWORK_ATTACH_FAIL, NULL); 00970 goto exit; 00971 } 00972 00973 /* Go back to old partition */ 00974 tr_debug("Back to old partition"); 00975 00976 /* If scanned parent is from other partition, delete from MLE table */ 00977 if (scanned_parent->leader_data.partitionId != thread_info(cur)->thread_leader_data->partitionId) { 00978 memcpy(ll64, ADDR_LINK_LOCAL_PREFIX , 8); 00979 memcpy(&ll64[8], scanned_parent->mac64 , 8); 00980 ll64[8] ^= 2; 00981 00982 entry_temp = mle_class_get_entry_by_ll64(cur->id, scanned_parent->linkMarginToParent, ll64, false); 00983 if (entry_temp) { 00984 mle_class_remove_entry(cur->id, entry_temp); 00985 } 00986 } 00987 00988 if (thread_info(cur)->thread_endnode_parent) { 00989 mac_helper_coordinator_address_set(cur, ADDR_802_15_4_LONG , thread_info(cur)->thread_endnode_parent->mac64); 00990 } 00991 if (cur->thread_info->routerShortAddress == 0xfffe || 00992 !thread_is_router_addr(cur->thread_info->routerShortAddress)) { 00993 thread_info(cur)->thread_attached_state = THREAD_STATE_CONNECTED; 00994 } else { 00995 thread_info(cur)->thread_attached_state = THREAD_STATE_CONNECTED_ROUTER; 00996 } 00997 00998 cur->thread_info->localServerDataBase.release_old_address = false; 00999 cur->thread_info->releaseRouterId = false; 01000 01001 cur->nwk_bootstrap_state = ER_BOOTSRAP_DONE; 01002 mle_service_interface_receiver_handler_update(cur->id, thread_general_mle_receive_cb); 01003 01004 exit: 01005 ns_dyn_mem_free(cur->thread_info->thread_attach_scanned_parent); 01006 cur->thread_info->thread_attach_scanned_parent = NULL; 01007 01008 return false; 01009 } 01010 01011 static uint8_t *thread_single_address_registration_tlv_write(uint8_t *ptr, lowpan_context_t *ctx, uint8_t *addressPtr) 01012 { 01013 *ptr++ = MLE_TYPE_ADDRESS_REGISTRATION; 01014 if (ctx) { 01015 *ptr++ = 9; 01016 //Write TLV to list 01017 *ptr++ = (ctx->cid | 0x80); 01018 memcpy(ptr, addressPtr + 8, 8); 01019 ptr += 8; 01020 } else { 01021 *ptr++ = 17; 01022 //Write TLV to list 01023 *ptr++ = 0; 01024 memcpy(ptr, addressPtr, 16); 01025 ptr += 16; 01026 } 01027 return ptr; 01028 } 01029 01030 static int thread_attach_child_id_request_build(protocol_interface_info_entry_t *cur) 01031 { 01032 uint8_t *ptr, *address_ptr; 01033 uint8_t mode; 01034 mle_message_timeout_params_t timeout; 01035 uint32_t keySequence; 01036 uint16_t buf_id = mle_service_msg_allocate(cur->id, 128, false, MLE_COMMAND_CHILD_ID_REQUEST); 01037 if (buf_id == 0) { 01038 return -1; 01039 } 01040 01041 thread_scanned_parent_t *scan_parent = thread_info(cur)->thread_attach_scanned_parent; 01042 01043 //Set ll64 01044 address_ptr = mle_service_get_msg_destination_address_pointer(buf_id); 01045 memcpy(address_ptr, ADDR_LINK_LOCAL_PREFIX, 8); 01046 memcpy(address_ptr + 8 , scan_parent->mac64, 8); 01047 address_ptr[8] ^= 2; 01048 01049 thread_management_get_current_keysequence(cur->id, &keySequence); 01050 mle_service_msg_update_security_params(buf_id, 5, 2, keySequence); 01051 01052 lowpan_context_t *ctx; 01053 uint8_t ml64[16]; 01054 uint8_t request_tlv_list[3]; 01055 uint8_t macShort[2]; 01056 uint8_t reqTlvCnt; 01057 mode = thread_mode_get_by_interface_ptr(cur); 01058 common_write_16_bit(scan_parent->shortAddress, macShort); 01059 //SET Coordinator Address 01060 mac_helper_coordinator_address_set(cur, ADDR_802_15_4_LONG , scan_parent->mac64); 01061 01062 ptr = mle_service_get_data_pointer(buf_id); 01063 /* Allocate a new challenge */ 01064 ptr = mle_tlv_write_mode(ptr, thread_mode_get_by_interface_ptr(cur)); 01065 ptr = mle_general_write_link_layer_framecounter(ptr, cur); 01066 //SET MLE Frame Counter 01067 ptr = mle_tlv_write_framecounter(ptr, mle_service_security_get_frame_counter(cur->id)); 01068 ptr = mle_tlv_write_response(ptr, scan_parent->challengeData, scan_parent->chal_len); 01069 01070 //Add ML-EID 01071 memcpy(ml64, thread_info(cur)->threadPrivatePrefixInfo.ulaPrefix, 8); 01072 memcpy(&ml64[8], cur->iid_slaac, 8); 01073 if ((mode & MLE_FFD_DEV) == 0) { 01074 ctx = lowpan_context_get_by_address(&cur->lowpan_contexts, ml64); 01075 if (ctx) { 01076 //Write TLV to list 01077 ptr = thread_single_address_registration_tlv_write(ptr, ctx, ml64); 01078 } 01079 } 01080 reqTlvCnt = 2; 01081 request_tlv_list[0] = MLE_TYPE_NETWORK_DATA; 01082 01083 request_tlv_list[1] = MLE_TYPE_ADDRESS16; 01084 if (thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) { 01085 request_tlv_list[2] = MLE_TYPE_ROUTE; 01086 reqTlvCnt = 3; 01087 } 01088 ptr = mle_tlv_req_tlv(ptr, request_tlv_list, reqTlvCnt); 01089 ptr = mle_tlv_write_timeout(ptr, cur->thread_info->host_link_timeout); 01090 //Set Version 01091 ptr = mle_tlv_write_version(ptr, cur->thread_info->version); 01092 //add only active timestamp to the child id request 01093 ptr = thread_active_timestamp_write(cur, ptr); 01094 01095 if (mle_service_update_length_by_ptr(buf_id,ptr)!= 0) { 01096 tr_debug("Buffer overflow at message write"); 01097 } 01098 timeout.retrans_max = THREAD_CHILD_ID_REQUEST_MAX_RETRY_CNT; 01099 timeout.timeout_init = 1; 01100 timeout.timeout_max = 3; 01101 timeout.delay = MLE_NO_DELAY; 01102 01103 mle_service_set_packet_callback(buf_id, thread_child_id_req_timeout); 01104 mle_service_set_msg_timeout_parameters(buf_id, &timeout); 01105 mle_service_send_message(buf_id); 01106 //Update MLE handler state 01107 mle_service_interface_receiver_handler_update(cur->id, thread_mle_child_request_receive_cb); 01108 cur->nwk_bootstrap_state = ER_CHILD_ID_REQ; 01109 scan_parent->child_id_request_id = buf_id; 01110 return 0; 01111 } 01112 01113 static bool thread_child_update_timeout_cb(int8_t interface_id, uint16_t msgId, bool usedAllRerties) 01114 { 01115 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 01116 (void)msgId; 01117 if (!cur || !cur->thread_info->thread_endnode_parent) { 01118 return false; 01119 } 01120 tr_debug("Child Update CB"); 01121 if (cur->thread_info->thread_endnode_parent->childUpdateProcessStatus) { 01122 //This process is ready 01123 cur->thread_info->thread_endnode_parent->childUpdateProcessStatus = false; 01124 if (!cur->thread_info->thread_endnode_parent->childUpdatePending) { 01125 01126 cur->thread_info->thread_endnode_parent->childUpdateProcessActive = false; 01127 //Disable Poll 01128 mac_data_poll_protocol_poll_mode_decrement(cur); 01129 tr_debug("Child Update ready"); 01130 } else { 01131 cur->thread_info->thread_endnode_parent->childUpdatePending = false; 01132 tr_debug("Child Update Pending"); 01133 thread_bootsrap_event_trig(THREAD_CHILD_UPDATE, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT); 01134 } 01135 return false; 01136 } 01137 01138 if (usedAllRerties) { 01139 01140 cur->thread_info->thread_endnode_parent->childUpdatePending = false; 01141 cur->thread_info->thread_endnode_parent->childUpdateProcessActive = false; 01142 cur->thread_info->thread_endnode_parent->childUpdateProcessStatus = false; 01143 mac_data_poll_protocol_poll_mode_decrement(cur); 01144 thread_bootstrap_reset_restart(cur->id); 01145 tr_debug("Restart attachment"); 01146 return false; 01147 } 01148 01149 return true; 01150 01151 } 01152 01153 int8_t thread_bootstrap_child_update(protocol_interface_info_entry_t *cur) 01154 { 01155 mle_message_timeout_params_t timeout; 01156 uint8_t mode; 01157 uint32_t keySequence; 01158 01159 if (!cur->thread_info->thread_endnode_parent) { 01160 return -1; 01161 } 01162 01163 tr_debug("Child Update Request"); 01164 01165 mode = thread_mode_get_by_interface_ptr(cur); 01166 01167 //Build packet 01168 01169 uint16_t bufId = mle_service_msg_allocate(cur->id, 150 + 3 + 6 + 10, false, MLE_COMMAND_CHILD_UPDATE_REQUEST); 01170 if (bufId == 0) { 01171 return -1; 01172 } 01173 01174 thread_management_get_current_keysequence(cur->id, &keySequence); 01175 mle_service_msg_update_security_params(bufId, 5, 2, keySequence); 01176 01177 uint8_t *address_ptr = mle_service_get_msg_destination_address_pointer(bufId); 01178 memcpy(address_ptr, ADDR_LINK_LOCAL_PREFIX, 8); 01179 memcpy(address_ptr + 8, cur->thread_info->thread_endnode_parent->mac64, 8); 01180 address_ptr[8] ^= 2; 01181 01182 uint8_t *ptr = mle_service_get_data_pointer(bufId); 01183 ptr = mle_tlv_write_mode(ptr, mode); 01184 ptr = mle_tlv_write_timeout(ptr, cur->thread_info->host_link_timeout); 01185 ptr = thread_leader_data_tlv_write(ptr, cur); 01186 01187 //Set Addresss TLV 01188 if ((mode & MLE_FFD_DEV) == 0) { 01189 ptr = thread_address_registration_tlv_write(ptr, cur); 01190 } 01191 01192 if (mle_service_update_length_by_ptr(bufId,ptr)!= 0) { 01193 tr_debug("Buffer overflow at message write"); 01194 } 01195 timeout.retrans_max = 3; 01196 timeout.timeout_init = 1; 01197 timeout.timeout_max = 4; 01198 timeout.delay = MLE_NO_DELAY; 01199 net_host_mode_t macHostMode; 01200 if (mac_data_poll_host_mode_get(cur,&macHostMode) == 0 && macHostMode == NET_HOST_RX_ON_IDLE) { 01201 thread_end_device_mode_set(cur, false); 01202 } 01203 mac_data_poll_init_protocol_poll(cur); 01204 mle_service_set_packet_callback(bufId, thread_child_update_timeout_cb); 01205 mle_service_set_msg_timeout_parameters(bufId, &timeout); 01206 mle_service_send_message(bufId); 01207 return 0; 01208 } 01209 int thread_host_bootstrap_child_update_negative_response(protocol_interface_info_entry_t *cur, uint8_t *dstAddress, mle_tlv_info_t *challenge) 01210 { 01211 uint32_t keySequence; 01212 01213 if (!challenge) { 01214 return -2; 01215 } 01216 01217 uint16_t bufId = mle_service_msg_allocate(cur->id, 16 + challenge->tlvLen, false, MLE_COMMAND_CHILD_UPDATE_RESPONSE); 01218 01219 if (bufId == 0) { 01220 return -1; 01221 } 01222 tr_debug("MLE Child negative Response"); 01223 01224 thread_management_get_current_keysequence(cur->id, &keySequence); 01225 mle_service_msg_update_security_params(bufId, 5, 2, keySequence); 01226 01227 uint8_t *ptr = mle_service_get_data_pointer(bufId); 01228 01229 *ptr++ = MLE_TYPE_STATUS; 01230 *ptr++ = 1; 01231 *ptr++ = MLE_STATUS_ERROR; 01232 01233 if (challenge->tlvLen) { 01234 //Add response 01235 ptr = mle_tlv_write_response(ptr, challenge->dataPtr, challenge->tlvLen); 01236 } 01237 01238 if (mle_service_update_length_by_ptr(bufId,ptr)!= 0) { 01239 tr_debug("Buffer overflow at message write"); 01240 } 01241 01242 mle_service_set_msg_destination_address(bufId, dstAddress); 01243 mle_service_send_message(bufId); 01244 return 0; 01245 } 01246 01247 01248 #endif 01249
Generated on Tue Jul 12 2022 13:03:20 by
