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