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: TYBLE16_simple_data_logger TYBLE16_MP3_Air
nd_router_object.c
00001 /* 00002 * Copyright (c) 2013-2019, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 #include "nsconfig.h" 00018 #ifdef HAVE_6LOWPAN_ND 00019 #include "ns_types.h" 00020 #include "string.h" 00021 #include "nsdynmemLIB.h" 00022 #include "ns_trace.h" 00023 #include "NWK_INTERFACE/Include/protocol.h" 00024 #include "Common_Protocols/icmpv6.h" 00025 #include "Common_Protocols/icmpv6_prefix.h" 00026 #include "Common_Protocols/icmpv6_radv.h" 00027 #include "randLIB.h" 00028 #ifdef HAVE_RPL 00029 #include "RPL/rpl_control.h" 00030 #include "RPL/rpl_data.h" 00031 #endif 00032 #include "MLE/mle.h" 00033 #include "6LoWPAN/IPHC_Decode/cipv6.h" 00034 #include "6LoWPAN/ND/nd_router_object.h" 00035 #include "6LoWPAN/Bootstraps/network_lib.h" 00036 #include "6LoWPAN/Bootstraps/protocol_6lowpan.h" 00037 #include "6LoWPAN/Bootstraps/protocol_6lowpan_bootstrap.h" 00038 #include "6LoWPAN/MAC/mac_helper.h" 00039 #include "Service_Libs/whiteboard/whiteboard.h" 00040 #include "common_functions.h" 00041 #include "BorderRouter/border_router.h" 00042 #include "Service_Libs/pan_blacklist/pan_blacklist_api.h" 00043 #include "6LoWPAN/MAC/mac_data_poll.h" 00044 #include "6LoWPAN/ws/ws_common.h" 00045 #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h" 00046 00047 #define TRACE_GROUP "loND" 00048 00049 void icmp_nd_router_object_release(nd_router_t *router_object); 00050 uint8_t icmp_nd_router_prefix_ttl_update(nd_router_t *nd_router_object, protocol_interface_info_entry_t *cur_interface, uint16_t seconds); 00051 static uint8_t nd_router_bootstrap_timer(nd_router_t *cur, protocol_interface_info_entry_t *cur_interface, uint16_t ticks); 00052 #ifdef HAVE_RPL 00053 static void nd_ra_build(nd_router_t *cur, const uint8_t *address, protocol_interface_info_entry_t *cur_interface); 00054 static void nd_ns_forward_timer_reset(uint8_t *root_adr); 00055 static void nd_router_forward_timer(nd_router_t *cur, uint16_t ticks_update); 00056 static nd_router_t *nd_router_object_scan_by_prefix(const uint8_t *prefix, nwk_interface_id nwk_id); 00057 #else 00058 #define nd_ra_build(cur, address, cur_interface) ((void)0) 00059 #define nd_ns_forward_timer_reset(root_adr) ((void)0) 00060 #define nd_router_forward_timer(root_adr, ticks_update) ((void)0) 00061 #define nd_router_object_scan_by_prefix(prefix, nwk_id) NULL 00062 #endif 00063 00064 static void lowpan_nd_address_cb(protocol_interface_info_entry_t *interface, if_address_entry_t *addr, if_address_callback_t reason); 00065 uint8_t nd_rs_build(nd_router_t *cur, protocol_interface_info_entry_t *cur_interface); 00066 bool icmp_nd_compare_to_def_next_hop(nd_router_next_hop *hop, sockaddr_t *adr); 00067 void icmp_nd_router_context_ttl_update(nd_router_t *nd_router_object, uint16_t seconds); 00068 00069 //ND Router List 00070 static NS_LARGE NS_LIST_DEFINE(nd_router_list, nd_router_t, link); 00071 00072 /* 00073 * Default values are documented in net_6lowpan_parameter_api.h - keep in sync. 00074 */ 00075 uint8_t nd_base_tick = 1; 00076 00077 nd_parameters_s nd_params = { 00078 .rs_retry_max = 3, 00079 .rs_retry_interval_min = 15, 00080 .ns_retry_interval_min = 100, 00081 .ns_retry_linear_backoff = 100, 00082 .timer_random_max = 31, 00083 .ns_retry_max = 5, 00084 .multihop_dad = true, 00085 .iids_map_to_mac = false, 00086 .send_nud_probes = true, 00087 .ra_interval_min = 160, 00088 .ra_transmits = 3, 00089 .ra_cur_hop_limit = ADV_CUR_HOP_LIMIT, 00090 .ra_link_mtu = 0, 00091 .ra_reachable_time = 0, 00092 .ra_retrans_timer = 0, 00093 .ns_forward_timeout = 300, 00094 }; 00095 00096 #ifdef HAVE_6LOWPAN_BORDER_ROUTER 00097 int8_t nd_set_br(nd_router_t *br) 00098 { 00099 if (ns_list_is_empty(&nd_router_list)) { 00100 ns_list_add_to_start(&nd_router_list, br); 00101 return 0; 00102 } 00103 return -1; 00104 } 00105 #endif 00106 00107 bool nd_object_active(void) 00108 { 00109 if (!ns_list_is_empty(&nd_router_list)) { 00110 return true; 00111 } 00112 return false; 00113 } 00114 00115 void icmp_nd_routers_init(void) 00116 { 00117 ns_list_foreach_safe(nd_router_t, cur, &nd_router_list) { 00118 ns_list_remove(&nd_router_list, cur); 00119 icmp_nd_router_object_release(cur); 00120 } 00121 } 00122 00123 00124 void icmp_nd_set_nd_def_router_address(uint8_t *ptr, nd_router_t *cur) 00125 { 00126 memcpy(ptr, ADDR_LINK_LOCAL_PREFIX, 8); 00127 ptr += 8; 00128 if (cur->default_hop.addrtype == ADDR_802_15_4_SHORT ) { 00129 memcpy(ptr, ADDR_SHORT_ADR_SUFFIC, 6); 00130 ptr += 6; 00131 *ptr++ = cur->default_hop.address[0]; 00132 *ptr = cur->default_hop.address[1]; 00133 } else { 00134 memcpy(ptr, cur->default_hop.address, 8); 00135 } 00136 } 00137 00138 void nd_ns_trig(nd_router_t *router_object, protocol_interface_info_entry_t *cur) 00139 { 00140 // 00141 ns_list_foreach(prefix_entry_t, prefix, &router_object->prefix_list) { 00142 if (prefix->options & PIO_A) { 00143 ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) { 00144 if (e->source == ADDR_SOURCE_SLAAC && (memcmp(e->address, prefix->prefix, 8) == 0)) { 00145 if (cur->if_6lowpan_dad_process.active) { 00146 e->state_timer = 5; 00147 } else { 00148 e->state_timer = 25; 00149 cur->if_6lowpan_dad_process.active = true; 00150 memcpy(cur->if_6lowpan_dad_process.address, e->address, 16); 00151 cur->if_6lowpan_dad_process.count = nd_params.ns_retry_max; 00152 } 00153 } 00154 } 00155 } 00156 } 00157 } 00158 00159 void nd_router_base_init(nd_router_t *new_entry) 00160 { 00161 ns_list_link_init(new_entry, link); 00162 new_entry->nd_timer = 0; 00163 new_entry->nd_bootstrap_tick = 0; 00164 new_entry->nd_re_validate = 0; 00165 new_entry->mle_advert_timer = 0; 00166 new_entry->mle_purge_timer = 0; 00167 new_entry->default_hop.addrtype = ADDR_NONE ; 00168 ns_list_init(&new_entry->prefix_list); 00169 ns_list_init(&new_entry->context_list); 00170 new_entry->secondaty_hop = 0; 00171 new_entry->ns_forward_timer = 0; 00172 new_entry->flags = 0; 00173 new_entry->ra_timing.initial_rtr_adv_count = 0; 00174 new_entry->ra_timing.rtr_adv_last_send_time = protocol_core_monotonic_time - 0x10000; 00175 new_entry->abro_version_num = 0; 00176 new_entry->trig_address_reg = false; 00177 } 00178 00179 static void nd_router_remove(nd_router_t *router, protocol_interface_info_entry_t *interface) 00180 { 00181 tr_debug("route remove"); 00182 icmpv6_stop_router_advertisements(interface, router->border_router); 00183 ns_list_remove(&nd_router_list, router); 00184 icmp_nd_router_object_release(router); 00185 00186 if (ns_list_is_empty(&nd_router_list)) { 00187 arm_6lowpan_bootstrap_init(interface); 00188 } 00189 } 00190 00191 nd_router_t *icmp_nd_router_object_get(const uint8_t *border_router, nwk_interface_id nwk_id) 00192 { 00193 nd_router_t *new_entry = 0; 00194 uint_fast8_t count = 0; 00195 00196 ns_list_foreach(nd_router_t, cur, &nd_router_list) { 00197 if (cur->nd_state == ND_BR_READY) { 00198 return NULL; 00199 } 00200 if (cur->nwk_id == nwk_id) { 00201 if (memcmp(cur->border_router, border_router, 16) == 0) { 00202 return cur; 00203 } 00204 } 00205 ++count; 00206 } 00207 00208 if (count >= ND_OBJECT_MAX) { 00209 return NULL; 00210 } 00211 00212 new_entry = ns_dyn_mem_alloc(sizeof(nd_router_t)); 00213 if (!new_entry) { 00214 tr_error("No heap for New Border Router"); 00215 return NULL; 00216 } 00217 00218 new_entry->nd_state = ND_READY; 00219 new_entry->nwk_id = nwk_id; 00220 nd_router_base_init(new_entry); 00221 memcpy(new_entry->border_router, border_router, 16); 00222 new_entry->trig_address_reg = false; 00223 ns_list_add_to_end(&nd_router_list, new_entry); 00224 00225 return new_entry; 00226 } 00227 00228 void icmp_nd_router_object_reset(nd_router_t *router_object) 00229 { 00230 icmpv6_prefix_list_free(&router_object->prefix_list); 00231 00232 lowpan_context_list_free(&router_object->context_list); 00233 00234 if (router_object->secondaty_hop) { 00235 ns_dyn_mem_free(router_object->secondaty_hop); 00236 router_object->secondaty_hop = 0; 00237 } 00238 } 00239 #ifdef HAVE_6LOWPAN_BORDER_ROUTER 00240 int8_t icmp_nd_router_prefix_proxy_update(uint8_t *dptr, nd_router_setup_t *nd_router_object) 00241 { 00242 prefix_entry_t *new_entry = 0; 00243 uint8_t pre_setups; 00244 uint32_t lifeTime, prefTime; 00245 uint8_t prefix_len = *dptr++; 00246 pre_setups = *dptr++; 00247 lifeTime = common_read_32_bit(dptr); 00248 dptr += 4; 00249 prefTime = common_read_32_bit(dptr); 00250 dptr += 4; 00251 pre_setups |= PIO_R; 00252 00253 new_entry = icmpv6_prefix_add(&nd_router_object->prefix_list, dptr, prefix_len, lifeTime, prefTime, pre_setups); 00254 if (new_entry) { 00255 new_entry->options = pre_setups; 00256 return 0; 00257 } 00258 return -2; 00259 } 00260 #endif 00261 00262 uint8_t icmp_nd_router_prefix_valid(nd_router_t *nd_router_object) 00263 { 00264 ns_list_foreach(prefix_entry_t, cur, &nd_router_object->prefix_list) { 00265 if ((cur->options & PIO_A) && cur->lifetime) { 00266 return 1; 00267 } 00268 } 00269 return 0; 00270 } 00271 00272 /* Returns 1 if the router object has been removed */ 00273 uint8_t icmp_nd_router_prefix_ttl_update(nd_router_t *nd_router_object, protocol_interface_info_entry_t *cur_interface, uint16_t seconds) 00274 { 00275 ns_list_foreach(prefix_entry_t, cur, &nd_router_object->prefix_list) { 00276 if (cur->preftime != 0xffffffff && cur->preftime) { 00277 if (cur->preftime <= seconds) { 00278 tr_warn("PREFTIME zero"); 00279 cur->preftime = 0; 00280 } else { 00281 cur->preftime -= seconds; 00282 } 00283 00284 } 00285 00286 if (cur->lifetime != 0xffffffff && cur->lifetime) { 00287 if (cur->lifetime > seconds) { 00288 cur->lifetime -= seconds; 00289 } else { 00290 tr_debug("Prefix Expiry"); 00291 if (nd_router_object->nd_state != ND_BR_READY) { 00292 if (cur->options & PIO_A) { 00293 tr_debug("Delete GP Address by Prefix, start RS"); 00294 nd_router_remove(nd_router_object, cur_interface); 00295 return 1; 00296 } 00297 } 00298 } 00299 } 00300 } 00301 00302 return 0; 00303 } 00304 00305 static int icmp_nd_slaac_prefix_address_gen(protocol_interface_info_entry_t *cur_interface, uint8_t *prefix, uint8_t prefix_len, uint32_t lifetime, uint32_t preftime, bool borRouterDevice, slaac_src_e slaac_src) 00306 { 00307 if_address_entry_t *address_entry = NULL; 00308 address_entry = icmpv6_slaac_address_add(cur_interface, prefix, prefix_len, lifetime, preftime, true, slaac_src); 00309 if (address_entry) { 00310 //Set Callback 00311 address_entry->cb = lowpan_nd_address_cb; 00312 if (borRouterDevice) { 00313 address_entry->state_timer = 0; 00314 } else { 00315 address_entry->state_timer = 45 + randLIB_get_random_in_range(1, nd_params.timer_random_max); 00316 //Allocate Addres registration state 00317 if (cur_interface->if_6lowpan_dad_process.active == false) { 00318 cur_interface->if_6lowpan_dad_process.count = nd_params.ns_retry_max; 00319 cur_interface->if_6lowpan_dad_process.active = true; 00320 memcpy(cur_interface->if_6lowpan_dad_process.address, address_entry->address, 16); 00321 } 00322 00323 if ((cur_interface->lowpan_info & INTERFACE_NWK_BOOTSRAP_ACTIVE) && cur_interface->nwk_bootstrap_state == ER_SCAN) { 00324 cur_interface->nwk_bootstrap_state = ER_ADDRESS_REQ; 00325 cur_interface->bootsrap_state_machine_cnt = 0; 00326 } 00327 } 00328 return 0; 00329 } 00330 return -1; 00331 } 00332 00333 00334 static void lowpan_nd_address_cb(protocol_interface_info_entry_t *interface, if_address_entry_t *addr, if_address_callback_t reason) 00335 { 00336 nd_router_t *cur = NULL; 00337 bool g16_address; 00338 tr_debug("Interface ID: %i, ipv6: %s", interface->id, trace_ipv6(addr->address)); 00339 00340 if (memcmp(&addr->address[8], ADDR_SHORT_ADR_SUFFIC, 6) == 0) { 00341 g16_address = true; 00342 } else { 00343 g16_address = false; 00344 } 00345 00346 switch (reason) { 00347 case ADDR_CALLBACK_DAD_COMPLETE: 00348 if (addr_ipv6_equal(interface->if_6lowpan_dad_process.address, addr->address)) { 00349 tr_info("Address REG OK: %s", trace_ipv6(interface->if_6lowpan_dad_process.address)); 00350 interface->if_6lowpan_dad_process.active = false; 00351 interface->global_address_available = true; 00352 //Check If GP16 Address Add LL16 Address 00353 if (interface->lowpan_info & INTERFACE_NWK_BOOTSRAP_ACTIVE) { 00354 if (g16_address) { 00355 //Register also GP64 if NET_6LOWPAN_MULTI_GP_ADDRESS mode is enabled 00356 if (interface->lowpan_address_mode == NET_6LOWPAN_MULTI_GP_ADDRESS) { 00357 if (icmp_nd_slaac_prefix_address_gen(interface, addr->address, addr->prefix_len, 00358 addr->valid_lifetime, addr->preferred_lifetime, false, SLAAC_IID_DEFAULT) == 0) { 00359 return; 00360 } else { 00361 tr_warning("Secondary Address allocate fail"); 00362 } 00363 } 00364 00365 } 00366 00367 protocol_6lowpan_bootstrap_nd_ready(interface); 00368 } else { 00369 //Disable protocol poll 00370 mac_data_poll_protocol_poll_mode_decrement(interface); 00371 } 00372 00373 } 00374 break; 00375 00376 case ADDR_CALLBACK_TIMER: 00377 tr_debug("State Timer CB"); 00378 if (interface->if_6lowpan_dad_process.active) { 00379 if (memcmp(addr->address, interface->if_6lowpan_dad_process.address, 16) == 0) { 00380 cur = nd_get_object_by_nwk_id(interface->nwk_id); 00381 } else { 00382 addr->state_timer = 5; 00383 } 00384 } else { 00385 cur = nd_get_object_by_nwk_id(interface->nwk_id); 00386 if (cur) { 00387 interface->if_6lowpan_dad_process.count = nd_params.ns_retry_max; 00388 interface->if_6lowpan_dad_process.active = true; 00389 memcpy(interface->if_6lowpan_dad_process.address, addr->address, 16); 00390 } else { 00391 tr_debug("No ND Object for Address"); 00392 } 00393 } 00394 00395 if (cur) { 00396 if (interface->if_6lowpan_dad_process.count) { 00397 nd_ns_build(cur, interface, addr->address); 00398 addr->state_timer = nd_params.ns_retry_interval_min; 00399 addr->state_timer += nd_params.ns_retry_linear_backoff * (nd_params.ns_retry_max - interface->if_6lowpan_dad_process.count); 00400 addr->state_timer += (randLIB_get_16bit() & nd_params.timer_random_max); 00401 tr_debug("NS Configured"); 00402 interface->if_6lowpan_dad_process.count--; 00403 //Enable Protocol Poll mode 00404 if (interface->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE) { 00405 mac_data_poll_init_protocol_poll(interface); 00406 } 00407 } else { 00408 00409 //ND FAIL 00410 tr_error("NS Fail"); 00411 protocol_6lowpan_neighbor_remove(interface, cur->default_hop.address, cur->default_hop.addrtype); 00412 00413 if (cur->secondaty_hop) { 00414 tr_warn("Try Secondary Route"); 00415 memcpy(&cur->default_hop, cur->secondaty_hop, sizeof(nd_router_next_hop)); 00416 ns_dyn_mem_free(cur->secondaty_hop); 00417 cur->secondaty_hop = 0; 00418 interface->if_6lowpan_dad_process.count = nd_params.ns_retry_max; 00419 addr->state_timer = 1; 00420 } else { 00421 interface->if_6lowpan_dad_process.active = false; 00422 protocol_6lowpan_nd_borderrouter_connection_down(interface); 00423 } 00424 } 00425 } 00426 00427 break; 00428 00429 case ADDR_CALLBACK_PARENT_FULL: 00430 interface->if_6lowpan_dad_process.count = 0; 00431 tr_error("ND cache full--> Black list by given lifetime"); 00432 cur = nd_get_object_by_nwk_id(interface->nwk_id); 00433 if (cur) { 00434 pan_blacklist_pan_set(&interface->pan_blaclist_cache, mac_helper_panid_get(interface), cur->life_time); 00435 } 00436 break; 00437 00438 case ADDR_CALLBACK_DAD_FAILED: 00439 if (g16_address) { 00440 tr_warn("ARO Failure:Duplicate address"); 00441 uint16_t shortAddress = common_read_16_bit(&addr->address[14]); 00442 tr_warn("Del old ll16"); 00443 protocol_6lowpan_del_ll16(interface, shortAddress); 00444 //Check if Application not freeze new address allocartion 00445 if (interface->reallocate_short_address_if_duplicate) { 00446 00447 protocol_6lowpan_allocate_mac16(interface); 00448 interface->if_6lowpan_dad_process.active = false; 00449 if (icmp_nd_slaac_prefix_address_gen(interface, addr->address, addr->prefix_len, 00450 addr->valid_lifetime, addr->preferred_lifetime, false, SLAAC_IID_6LOWPAN_SHORT) == 0) { 00451 addr->state_timer = 1; 00452 return; 00453 } 00454 } 00455 } 00456 bootsrap_next_state_kick(ER_BOOTSTRAP_DAD_FAIL, interface); 00457 00458 break; 00459 00460 default: 00461 break; 00462 } 00463 } 00464 00465 int8_t icmp_nd_router_prefix_update(uint8_t *dptr, nd_router_t *nd_router_object, protocol_interface_info_entry_t *cur_interface) 00466 { 00467 slaac_src_e slaac_src; 00468 bool borRouterDevice; 00469 prefix_entry_t *new_entry = 0; 00470 uint8_t prefix_len = *dptr++; 00471 uint8_t pre_setups = *dptr++; 00472 uint32_t lifetime = common_read_32_bit(dptr); 00473 uint32_t preftime = common_read_32_bit(dptr + 4); 00474 00475 if (cur_interface->lowpan_address_mode == NET_6LOWPAN_GP16_ADDRESS 00476 || cur_interface->lowpan_address_mode == NET_6LOWPAN_MULTI_GP_ADDRESS) { 00477 slaac_src = SLAAC_IID_6LOWPAN_SHORT; 00478 } else { 00479 slaac_src = SLAAC_IID_DEFAULT; 00480 } 00481 if (cur_interface->border_router_setup) { 00482 borRouterDevice = true; 00483 } else { 00484 borRouterDevice = false; 00485 } 00486 00487 //Read Lifetimes + skip resertved 4 bytes 00488 dptr += 12; 00489 new_entry = icmpv6_prefix_add(&nd_router_object->prefix_list, dptr, prefix_len, lifetime, preftime, pre_setups); 00490 if (new_entry) { 00491 if (new_entry->options == 0xff) { 00492 new_entry->options = pre_setups; 00493 if (new_entry->options & PIO_A) { 00494 if (icmpv6_slaac_prefix_update(cur_interface, new_entry->prefix, new_entry->prefix_len, new_entry->lifetime, new_entry->preftime) != 0) { 00495 icmp_nd_slaac_prefix_address_gen(cur_interface, new_entry->prefix, new_entry->prefix_len, new_entry->lifetime, new_entry->preftime, borRouterDevice, slaac_src); 00496 } 00497 } 00498 } else { 00499 icmpv6_slaac_prefix_update(cur_interface, dptr, prefix_len, lifetime, preftime); 00500 } 00501 00502 if (nd_router_object->trig_address_reg) { 00503 nd_router_object->trig_address_reg = false; 00504 icmpv6_slaac_prefix_register_trig(cur_interface, dptr, prefix_len); 00505 } 00506 00507 return 0; 00508 } 00509 00510 return -2; 00511 } 00512 00513 /* Update lifetime and expire contexts in ABRO storage */ 00514 void icmp_nd_router_context_ttl_update(nd_router_t *nd_router_object, uint16_t seconds) 00515 { 00516 ns_list_foreach_safe(lowpan_context_t, cur, &nd_router_object->context_list) { 00517 /* We're using seconds in call, but lifetime is in 100ms ticks */ 00518 if (cur->lifetime <= (uint32_t)seconds * 10) { 00519 /* When lifetime in the ABRO storage runs out, just drop it, 00520 * so we stop advertising it. This is different from the 00521 * interface context handling. 00522 */ 00523 ns_list_remove(&nd_router_object->context_list, cur); 00524 ns_dyn_mem_free(cur); 00525 } else { 00526 cur->lifetime -= (uint32_t)seconds * 10; 00527 } 00528 } 00529 } 00530 00531 void icmp_nd_router_object_release(nd_router_t *router_object) 00532 { 00533 if (router_object) { 00534 icmp_nd_router_object_reset(router_object); 00535 ns_dyn_mem_free(router_object); 00536 } 00537 } 00538 00539 00540 void icmp_nd_border_router_release(nd_router_t *router_object) 00541 { 00542 if (router_object) { 00543 if (!ns_list_is_empty(&nd_router_list)) { 00544 ns_list_remove(&nd_router_list, router_object); 00545 } 00546 icmp_nd_router_object_reset(router_object); 00547 } 00548 } 00549 00550 00551 00552 void gp_address_list_free(gp_ipv6_address_list_t *list) 00553 { 00554 ns_list_foreach_safe(gp_ipv6_address_entry_t, cur, list) { 00555 ns_list_remove(list, cur); 00556 ns_dyn_mem_free(cur); 00557 } 00558 } 00559 00560 /* 00561 * Parse 6LoWPAN Context Options (RFC 6775 4.2) for ABRO storage. 00562 * 00563 * 0 1 2 3 00564 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 00565 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00566 * | Type | Length |Context Length | Res |C| CID | 00567 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00568 * | Reserved | Valid Lifetime | 00569 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00570 * . . 00571 * . Context Prefix . 00572 * . . 00573 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00574 * 00575 */ 00576 static void icmp_nd_context_parse(buffer_t *buf, nd_router_t *nd_router_object) 00577 { 00578 const uint8_t *dptr = buffer_data_pointer(buf); 00579 uint16_t data_len = buffer_data_length(buf); 00580 uint16_t read = 0; 00581 00582 while (read < data_len) { 00583 uint8_t type = dptr[0]; 00584 uint16_t len = dptr[1] * 8; 00585 00586 read += len; 00587 00588 if (len == 0 || read > data_len) { 00589 return; 00590 } else if (type == ICMPV6_OPT_6LOWPAN_CONTEXT) { 00591 uint8_t ctx_len = dptr[2]; 00592 00593 if ((len == 16 && ctx_len <= 64) || (len == 24 && ctx_len <= 128)) { 00594 uint8_t c_id = dptr[3] & 0x1f; // ignore reserved fields 00595 uint16_t lifetime_mins = common_read_16_bit(dptr + 6); 00596 00597 lowpan_context_update(&nd_router_object->context_list, c_id, lifetime_mins, dptr + 8, ctx_len, true); 00598 } else { 00599 tr_warn("Context len fail"); 00600 } 00601 } 00602 dptr += len; 00603 } 00604 } 00605 00606 void icmp_nd_prefixs_parse(buffer_t *buf, nd_router_t *nd_router_object, protocol_interface_info_entry_t *cur_interface) 00607 { 00608 uint8_t *dptr; 00609 uint16_t data_len = buffer_data_length(buf); 00610 uint16_t readed = 0; 00611 uint8_t type, len; 00612 dptr = buffer_data_pointer(buf); 00613 while (readed < data_len) { 00614 type = *dptr++; 00615 len = *dptr++; 00616 if (len == 0) { 00617 return; 00618 } 00619 len <<= 3; 00620 readed += len; 00621 00622 if (readed > data_len) { 00623 return; 00624 } else if (type == ICMPV6_OPT_PREFIX_INFO && len == 32) { 00625 icmp_nd_router_prefix_update(dptr, nd_router_object, cur_interface); 00626 dptr += 30; 00627 } else { 00628 dptr += (len - 2); 00629 } 00630 } 00631 } 00632 00633 00634 void icmp_nd_set_next_hop(nd_router_next_hop *hop, sockaddr_t *adr) 00635 { 00636 uint8_t *ptr = 0; 00637 ptr = hop->address; 00638 if (adr->addr_type == ADDR_IPV6 ) { 00639 if (memcmp(&adr->address [8], ADDR_SHORT_ADR_SUFFIC, 6) == 0) { 00640 hop->addrtype = ADDR_802_15_4_SHORT ; 00641 memcpy(ptr, &adr->address [14], 2); 00642 } else { 00643 hop->addrtype = ADDR_802_15_4_LONG ; 00644 memcpy(ptr, &adr->address [8], 8); 00645 } 00646 } else { 00647 hop->addrtype = adr->addr_type ; 00648 memcpy(ptr, &adr->address [2], 8); 00649 } 00650 } 00651 00652 bool icmp_nd_compare_to_def_next_hop(nd_router_next_hop *hop, sockaddr_t *adr) 00653 { 00654 if (adr->addr_type == ADDR_IPV6 ) { 00655 if (memcmp(&adr->address [8], ADDR_SHORT_ADR_SUFFIC, 6) == 0) { 00656 if (hop->addrtype == ADDR_802_15_4_SHORT ) { 00657 if (memcmp(hop->address, &adr->address [14], 2) == 0) { 00658 return false; 00659 } 00660 } 00661 } else { 00662 if (hop->addrtype == ADDR_802_15_4_LONG ) { 00663 if (memcmp(hop->address, &adr->address [8], 8) == 0) { 00664 return false; 00665 } 00666 } 00667 00668 } 00669 } else { 00670 hop->addrtype = adr->addr_type ; 00671 memcpy(hop->address, &adr->address [2], 8); 00672 } 00673 return true; 00674 } 00675 00676 uint8_t nd_rs_build(nd_router_t *cur, protocol_interface_info_entry_t *cur_interface) 00677 { 00678 buffer_t *buf; 00679 00680 if (cur) { 00681 uint8_t dest_addr[16]; 00682 icmp_nd_set_nd_def_router_address(dest_addr, cur); 00683 buf = icmpv6_build_rs(cur_interface, dest_addr); 00684 } else { 00685 buf = icmpv6_build_rs(cur_interface, NULL); 00686 } 00687 00688 if (buf) { 00689 arm_net_protocol_packet_handler(buf, cur_interface); 00690 return 1; 00691 } 00692 return 0; 00693 } 00694 00695 #ifdef HAVE_RPL 00696 static bool rpl_parents_only(const ipv6_route_info_t *route, bool valid) 00697 { 00698 return valid && rpl_data_is_rpl_parent_route(route->source); 00699 } 00700 #endif 00701 00702 /* Neighbor Solicitation (RFC4861) with Address Registration Option (RFC6775) 00703 * and Source Link-Layer Address Option (RFC4861) 00704 */ 00705 void nd_ns_build(nd_router_t *cur, protocol_interface_info_entry_t *cur_interface, uint8_t *address_ptr) 00706 { 00707 uint8_t router[16]; 00708 aro_t aro; 00709 buffer_t *buf; 00710 00711 #ifdef HAVE_RPL 00712 /* If we're a host, we will just send to our ND parent. But as a router, 00713 * we don't really maintain our ND parent - send NA instead to the RPL 00714 * parent we would use to talk to the border router. 00715 */ 00716 if ((cur_interface->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) && cur_interface->rpl_domain) { 00717 ipv6_route_t *route = ipv6_route_choose_next_hop(cur->border_router, cur_interface->id, rpl_parents_only); 00718 if (!route) { 00719 /* Important to return 1 so this counts as a "success" - caller then backs off due to lack of response and time out */ 00720 return; 00721 } 00722 memcpy(router, route->info.next_hop_addr, 16); 00723 } else 00724 #endif 00725 { 00726 icmp_nd_set_nd_def_router_address(router, cur); 00727 } 00728 00729 aro.status = ARO_SUCCESS; 00730 aro.present = true; 00731 aro.lifetime = (cur->life_time / 60) + 1; 00732 memcpy(aro.eui64, cur_interface->mac, 8); 00733 00734 buf = icmpv6_build_ns(cur_interface, router, address_ptr, true, false, &aro); 00735 protocol_push(buf); 00736 } 00737 00738 /* RFC 6775 Duplicate Address Request/Confirmation packets 00739 * 00740 * 0 1 2 3 00741 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 00742 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00743 * | Type | Code | Checksum | 00744 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00745 * | Status | Reserved | Registration Lifetime | 00746 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00747 * | | 00748 * + EUI-64 + 00749 * | | 00750 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00751 * | | 00752 * + + 00753 * | | 00754 * + Registered Address + 00755 * | | 00756 * + + 00757 * | | 00758 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00759 * 00760 * (and 8.2.1 implies this is can be followed by options, although 00761 * none are defined). 00762 */ 00763 #ifdef HAVE_6LOWPAN_ROUTER 00764 static bool nd_dar_dac_valid(buffer_t *buf) 00765 { 00766 const uint8_t *dptr = buffer_data_pointer(buf); 00767 00768 if (buf->options .code != 0) { 00769 return false; 00770 } 00771 00772 if (!icmpv6_options_well_formed_in_buffer(buf, 28)) { 00773 return false; 00774 } 00775 00776 if (addr_is_ipv6_multicast(dptr + 12)) { 00777 return false; 00778 } 00779 00780 if (addr_is_ipv6_unspecified(buf->src_sa .address ) || 00781 addr_is_ipv6_multicast(buf->src_sa .address )) { 00782 return false; 00783 } 00784 00785 return true; 00786 } 00787 #endif 00788 00789 buffer_t *nd_dar_parse(buffer_t *buf, protocol_interface_info_entry_t *cur_interface) 00790 { 00791 #if defined WHITEBOARD && defined HAVE_6LOWPAN_BORDER_ROUTER 00792 uint8_t *dptr = buffer_data_pointer(buf); 00793 buffer_t *retbuf; 00794 uint8_t status; 00795 uint16_t lifetime; 00796 const uint8_t *eui64; 00797 00798 if (!nd_dar_dac_valid(buf)) { 00799 goto drop; 00800 } 00801 00802 status = *dptr; 00803 dptr += 2; 00804 lifetime = common_read_16_bit(dptr); 00805 dptr += 2; 00806 00807 if (status != ARO_SUCCESS) { 00808 goto drop; 00809 } 00810 00811 whiteboard_entry_t *wb; 00812 00813 /* EUI-64 */ 00814 eui64 = dptr; 00815 dptr += 8; 00816 tr_debug("DAR adr: %s, from %s", trace_ipv6(dptr), trace_ipv6(buf->src_sa .address )); 00817 00818 //SET White board 00819 wb = whiteboard_table_update(dptr, eui64, &status); 00820 if (wb && status == ARO_SUCCESS) { 00821 memcpy(wb->address, dptr, 16); 00822 memcpy(wb->eui64, eui64, 8); 00823 wb->interface_index = cur_interface->id; 00824 wb->ttl = UINT24_C(60) * lifetime; 00825 } 00826 00827 retbuf = icmpv6_build_dad(cur_interface, NULL, ICMPV6_TYPE_INFO_DAC, buf->src_sa .address , eui64, dptr, status, lifetime); 00828 if (retbuf) { 00829 buffer_free(buf); 00830 return retbuf; 00831 } 00832 00833 drop: 00834 #else 00835 (void)cur_interface; 00836 #endif 00837 00838 return buffer_free(buf); 00839 } 00840 00841 #ifdef HAVE_6LOWPAN_ROUTER 00842 static void nd_update_registration(protocol_interface_info_entry_t *cur_interface, ipv6_neighbour_t *neigh, const aro_t *aro) 00843 { 00844 /* We are about to send an ARO response - update our Neighbour Cache accordingly */ 00845 if (aro->status == ARO_SUCCESS && aro->lifetime != 0) { 00846 neigh->type = IP_NEIGHBOUR_REGISTERED; 00847 neigh->lifetime = aro->lifetime * UINT32_C(60); 00848 ipv6_neighbour_set_state(&cur_interface->ipv6_neighbour_cache, neigh, IP_NEIGHBOUR_STALE); 00849 /* Register with 2 seconds off the lifetime - don't want the NCE to expire before the route */ 00850 ipv6_route_add_metric(neigh->ip_address, 128, cur_interface->id, neigh->ip_address, ROUTE_ARO, NULL, 0, neigh->lifetime - 2, 32); 00851 00852 /* We need to know peer is a host before publishing - this needs MLE. Not yet established 00853 * what to do without MLE - might need special external/non-external prioritisation at root. 00854 * This "publish for RFD" rule comes from ZigBee IP. 00855 */ 00856 mac_neighbor_table_entry_t *entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur_interface), ipv6_neighbour_eui64(&cur_interface->ipv6_neighbour_cache, neigh), ADDR_802_15_4_LONG ); 00857 00858 if (entry) { 00859 if (ws_info(cur_interface)) { 00860 ws_common_etx_validate(cur_interface, entry); 00861 } 00862 00863 if (!entry->ffd_device ) { 00864 rpl_control_publish_host_address(protocol_6lowpan_rpl_domain, neigh->ip_address, neigh->lifetime); 00865 } 00866 } 00867 protocol_6lowpan_neighbor_address_state_synch(cur_interface, aro->eui64, neigh->ip_address + 8); 00868 00869 } else { 00870 /* Um, no - can't transmit response if we remove NCE now! */ 00871 //ipv6_neighbour_entry_remove(&cur_interface->ipv6_neighbour_cache, neigh); 00872 neigh->type = IP_NEIGHBOUR_TENTATIVE; 00873 neigh->lifetime = 2; 00874 ipv6_neighbour_set_state(&cur_interface->ipv6_neighbour_cache, neigh, IP_NEIGHBOUR_STALE); 00875 ipv6_route_add_metric(neigh->ip_address, 128, cur_interface->id, neigh->ip_address, ROUTE_ARO, NULL, 0, 4, 32); 00876 rpl_control_unpublish_address(protocol_6lowpan_rpl_domain, neigh->ip_address); 00877 } 00878 } 00879 00880 void nd_remove_registration(protocol_interface_info_entry_t *cur_interface, addrtype_t ll_type, const uint8_t *ll_address) 00881 { 00882 ns_list_foreach_safe(ipv6_neighbour_t, cur, &cur_interface->ipv6_neighbour_cache.list) { 00883 if ((cur->type == IP_NEIGHBOUR_REGISTERED 00884 || cur->type == IP_NEIGHBOUR_TENTATIVE) 00885 && ipv6_neighbour_ll_addr_match(cur, ll_type, ll_address)) { 00886 00887 ipv6_route_delete(cur->ip_address, 128, cur_interface->id, cur->ip_address, 00888 ROUTE_ARO); 00889 ipv6_neighbour_entry_remove(&cur_interface->ipv6_neighbour_cache, 00890 cur); 00891 } 00892 } 00893 } 00894 00895 /* Process ICMP Neighbor Solicitation (RFC 4861 + RFC 6775) ARO. */ 00896 bool nd_ns_aro_handler(protocol_interface_info_entry_t *cur_interface, const uint8_t *aro_opt, const uint8_t *slla_opt, const uint8_t *src_addr, aro_t *aro_out) 00897 { 00898 /* Ignore any ARO if source is link-local */ 00899 if (addr_is_ipv6_link_local(src_addr)) { 00900 return true; /* Transmit NA, without ARO */ 00901 } 00902 00903 /* If we can't parse the SLLAO, then act as if no SLLAO: ignore ARO */ 00904 sockaddr_t ll_addr; 00905 if (!cur_interface->if_llao_parse(cur_interface, slla_opt, &ll_addr)) { 00906 return true; /* Transmit NA, without ARO */ 00907 } 00908 00909 /* 00910 * 0 1 2 3 00911 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 00912 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00913 * | Type = 33 | Length = 2 | Status | Reserved | 00914 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00915 * | Reserved | Registration Lifetime | 00916 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00917 * | | 00918 * + EUI-64 + 00919 * | | 00920 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00921 */ 00922 /* icmpv6_ns_handler has already checked incoming status == 0 */ 00923 aro_out->lifetime = common_read_16_bit(aro_opt + 6); 00924 memcpy(aro_out->eui64, aro_opt + 8, 8); 00925 00926 /* Check if we are already using this address ourself */ 00927 if (addr_interface_address_compare(cur_interface, src_addr) == 0) { 00928 aro_out->present = true; 00929 aro_out->status = ARO_DUPLICATE; 00930 return true; 00931 } 00932 00933 /* TODO - check hard upper limit on registrations? */ 00934 if (ws_info(cur_interface) && 00935 !ws_common_allow_child_registration(cur_interface, aro_out->eui64)) { 00936 aro_out->present = true; 00937 aro_out->status = ARO_FULL; 00938 return true; 00939 } 00940 00941 /* We need to have entry in the Neighbour Cache */ 00942 ipv6_neighbour_t *neigh = ipv6_neighbour_lookup_or_create(&cur_interface->ipv6_neighbour_cache, src_addr); 00943 if (!neigh) { 00944 aro_out->present = true; 00945 aro_out->status = ARO_FULL; 00946 return true; 00947 } 00948 00949 uint8_t *nce_eui64 = ipv6_neighbour_eui64(&cur_interface->ipv6_neighbour_cache, neigh); 00950 if (neigh->state != IP_NEIGHBOUR_NEW) { 00951 switch (neigh->type) { 00952 case IP_NEIGHBOUR_TENTATIVE: 00953 /* Is zero EUI-64 still possible? */ 00954 if (memcmp(nce_eui64, aro_out->eui64, 8) && memcmp(nce_eui64, ADDR_EUI64_ZERO, 8)) { 00955 /* Have a Tentative NCE with different EUI-64 - ignore NS; two 00956 * people trying to register at once. One should retry. 00957 */ 00958 return false; 00959 } 00960 break; 00961 case IP_NEIGHBOUR_REGISTERED: 00962 if (memcmp(nce_eui64, aro_out->eui64, 8)) { 00963 /* Already registered with different EUI-64 - duplicate */ 00964 aro_out->present = true; 00965 aro_out->status = ARO_DUPLICATE; 00966 return true; 00967 } 00968 break; 00969 case IP_NEIGHBOUR_GARBAGE_COLLECTIBLE: 00970 break; 00971 } 00972 } 00973 00974 if (neigh->type != IP_NEIGHBOUR_REGISTERED) { 00975 neigh->type = IP_NEIGHBOUR_TENTATIVE; 00976 neigh->lifetime = TENTATIVE_NCE_LIFETIME; 00977 memcpy(nce_eui64, aro_out->eui64, 8); 00978 } 00979 00980 /* Set the LL address, ensure it's marked STALE */ 00981 ipv6_neighbour_entry_update_unsolicited(&cur_interface->ipv6_neighbour_cache, neigh, ll_addr.addr_type , ll_addr.address ); 00982 ipv6_neighbour_set_state(&cur_interface->ipv6_neighbour_cache, neigh, IP_NEIGHBOUR_STALE); 00983 if (ws_info(cur_interface)) { 00984 aro_out->status = ARO_SUCCESS; 00985 aro_out->present = true; 00986 // Todo: this might not be needed... 00987 nd_update_registration(cur_interface, neigh, aro_out); 00988 return true; 00989 } 00990 if (cur_interface->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER || nd_params.multihop_dad == false) { 00991 if (cur_interface->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { 00992 whiteboard_entry_t *wb; 00993 wb = whiteboard_table_update(src_addr, aro_out->eui64, &aro_out->status); 00994 if (wb) { 00995 if (aro_out->status == ARO_SUCCESS) { 00996 memcpy(wb->address, src_addr, 16); 00997 memcpy(wb->eui64, aro_out->eui64, 8); 00998 wb->interface_index = cur_interface->id; 00999 wb->ttl = 50000;//life_time; 01000 } 01001 } else { 01002 tr_warn("white Board Registry fail"); 01003 aro_out->status = ARO_FULL; 01004 goto RESPONSE; 01005 } 01006 } 01007 01008 RESPONSE: 01009 aro_out->present = true; 01010 nd_update_registration(cur_interface, neigh, aro_out); 01011 return true; /* Transmit NA */ 01012 } else { /* Non-border router and multihop DAD: relay as DAR to Border Router */ 01013 nd_router_t *nd_router_obj = 0; 01014 01015 nd_router_obj = nd_router_object_scan_by_prefix(src_addr, cur_interface->nwk_id); 01016 if (!nd_router_obj) { 01017 /* Don't know where to send this. Do we say "yay" or "nay"? */ 01018 /* For now, ignore ARO, as with old code; don't set aro_out.present */ 01019 return true; 01020 } 01021 01022 buffer_t *buf = icmpv6_build_dad(cur_interface, NULL, ICMPV6_TYPE_INFO_DAR, nd_router_obj->border_router, aro_out->eui64, src_addr, 0, aro_out->lifetime); 01023 if (!buf) { 01024 return false; /* Failed to build DAR - drop NS */ 01025 } 01026 01027 tr_debug("RX:NS --> TX DAR to Root"); 01028 protocol_push(buf); 01029 if (nd_router_obj->ns_forward_timer == 0) { 01030 nd_router_obj->ns_forward_timer = nd_params.ns_forward_timeout; 01031 } 01032 01033 return false; /* Tell ns_handler to not transmit now */ 01034 } 01035 } 01036 01037 buffer_t *nd_dac_handler(buffer_t *buf, protocol_interface_info_entry_t *cur) 01038 { 01039 uint8_t *dptr, target_address[16], *reg_address; 01040 aro_t aro; 01041 01042 dptr = buffer_data_pointer(buf); 01043 01044 if (!nd_dar_dac_valid(buf)) { 01045 return buffer_free(buf); 01046 } 01047 01048 nd_ns_forward_timer_reset(buf->src_sa .address ); 01049 01050 aro.status = *dptr; 01051 dptr += 2; 01052 aro.lifetime = common_read_16_bit(dptr); 01053 dptr += 2; 01054 /* EUI-64 */ 01055 memcpy(aro.eui64, dptr, 8); 01056 dptr += 8; 01057 reg_address = dptr; 01058 dptr += 16; 01059 01060 ipv6_neighbour_t *neigh = ipv6_neighbour_lookup(&cur->ipv6_neighbour_cache, reg_address); 01061 if (!neigh || neigh->type == IP_NEIGHBOUR_GARBAGE_COLLECTIBLE || memcmp(ipv6_neighbour_eui64(&cur->ipv6_neighbour_cache, neigh), aro.eui64, 8)) { 01062 return buffer_free(buf); 01063 } 01064 01065 nd_update_registration(cur, neigh, &aro); 01066 01067 /* RFC 6775 has a bit of a hole here - what's the Target Address? */ 01068 /* It's not in the DAC. We didn't record locally when we sent the DAR */ 01069 /* I guess it's logical that we use a link-local address. We break */ 01070 /* RFC 4861 by responding "solicited", but not to the NS Target... */ 01071 /* However, my reading of RFC 4861 says that the receiver should do */ 01072 /* the right thing. Only problem is that what if they really did want */ 01073 /* to do a NUD probe for our GP addr, but included the ARO by mistake? */ 01074 if (addr_interface_get_ll_address(cur, target_address, 0)) { 01075 return buffer_free(buf); 01076 } 01077 01078 /* NA builder will send it to the address in the buffer's source */ 01079 memcpy(buf->src_sa .address , reg_address, 16); 01080 01081 buffer_t *na_buf = icmpv6_build_na(cur, true, true, false, target_address, &aro, buf->src_sa .address ); 01082 01083 buffer_free(buf); 01084 01085 return na_buf; 01086 } 01087 #endif // HAVE_6LOWPAN_ROUTER 01088 01089 /* Original ABRO-based all-in-one parser. This needs some rework to separate ABRO-related and unrelated bits */ 01090 /* Returns "false" if ABRO suggested it was a stale message, so not worth handling in the normal code */ 01091 bool nd_ra_process_abro(protocol_interface_info_entry_t *cur, buffer_t *buf, const uint8_t *dptr, uint8_t ra_flags, uint16_t router_lifetime) 01092 { 01093 nd_router_t *router; 01094 uint32_t abro_ver_num; 01095 uint16_t temp16; 01096 bool uptodate = false; 01097 01098 /* XXX this is really a 32-bit number these days */ 01099 temp16 = common_read_16_bit(dptr); 01100 abro_ver_num = temp16; 01101 dptr += 2; 01102 temp16 = common_read_16_bit(dptr); 01103 //SET MSB bytes to 32-bit 01104 abro_ver_num |= ((uint32_t)temp16 << 16); 01105 01106 dptr += 4; 01107 //If Border Router boot is state 01108 01109 if (cur->border_router_setup) { 01110 if (memcmp(dptr, cur->border_router_setup->border_router_gp_adr, 16) == 0) { 01111 if (cur->border_router_setup->initActive) { 01112 //save New Context 01113 if (common_serial_number_greater_32(abro_ver_num, cur->border_router_setup->nd_border_router_configure->abro_version_num)) { 01114 cur->border_router_setup->initActive = false; 01115 cur->border_router_setup->nd_border_router_configure->abro_version_num = (abro_ver_num + 0x00010000); 01116 cur->border_router_setup->nd_nwk->abro_version_num = (abro_ver_num + 0x00010000); 01117 } else if (abro_ver_num == cur->border_router_setup->nd_border_router_configure->abro_version_num) { 01118 01119 cur->border_router_setup->initActive = false; 01120 cur->border_router_setup->nd_border_router_configure->abro_version_num = (abro_ver_num + 0x00010000); 01121 cur->border_router_setup->nd_nwk->abro_version_num = (abro_ver_num + 0x00010000); 01122 } 01123 } 01124 return true; 01125 } 01126 return false; 01127 } 01128 01129 router = icmp_nd_router_object_get(dptr, buf->interface ->nwk_id); 01130 if (!router) { 01131 return true; 01132 } 01133 01134 if (router->default_hop.addrtype == ADDR_NONE ) { 01135 tr_debug("Create ND version"); 01136 01137 router->flags = ra_flags; 01138 01139 uptodate = true; 01140 icmp_nd_set_next_hop(&router->default_hop, &buf->src_sa ); 01141 router->default_hop.LQI = buf->options .lqi ; 01142 01143 icmp_nd_prefixs_parse(buf, router, cur); 01144 icmp_nd_context_parse(buf, router); 01145 01146 if ((cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) == 0) { 01147 //SET OnlY primary 01148 uint8_t address[8]; 01149 if (router->default_hop.addrtype == ADDR_802_15_4_SHORT ) { 01150 address[6] = router->default_hop.address[0]; 01151 address[7] = router->default_hop.address[1]; 01152 memcpy(address, ADDR_SHORT_ADR_SUFFIC, 6); 01153 } else { 01154 memcpy(address, router->default_hop.address, 8); 01155 } 01156 protocol_6lowpan_neighbor_priority_update(cur, NULL, address); 01157 } 01158 router->nd_state = ND_READY; 01159 router->nd_re_validate = (router_lifetime / 5) * 4; 01160 router->nd_timer = 10; 01161 } else { 01162 bool new_router = icmp_nd_compare_to_def_next_hop(&router->default_hop, &buf->src_sa ); 01163 01164 if (abro_ver_num == router->abro_version_num) { 01165 /* Up-to-date for host processing, but don't necessarily process for multi-hop relaying */ 01166 uptodate = true; 01167 } 01168 01169 /* XXX this is really a 32-bit number these days */ 01170 if (common_serial_number_greater_32(abro_ver_num, router->abro_version_num)) { 01171 uint32_t diff_update; 01172 diff_update = (abro_ver_num - router->abro_version_num); 01173 uptodate = true; 01174 01175 //uprouter_info=1; 01176 if (diff_update >= 0x00010000) { 01177 tr_debug("Border Router Boot Trig NS"); 01178 router->trig_address_reg = true; 01179 } else { 01180 tr_debug("Next num"); 01181 } 01182 01183 icmpv6_prefix_list_free(&router->prefix_list); 01184 01185 lowpan_context_list_free(&router->context_list); 01186 01187 icmp_nd_prefixs_parse(buf, router, cur); 01188 router->trig_address_reg = false; 01189 icmp_nd_context_parse(buf, router); 01190 icmpv6_restart_router_advertisements(cur, router->border_router); 01191 } else if (router->default_hop.LQI < buf->options .lqi ) { 01192 /* XXX another zero-hysteresis parent swap */ 01193 if (new_router) { 01194 uint8_t *sec_ptr = NULL; 01195 if (router->secondaty_hop == 0) { 01196 router->secondaty_hop = ns_dyn_mem_alloc(sizeof(nd_router_next_hop)); 01197 } else { 01198 nd_router_next_hop *hop = router->secondaty_hop; 01199 sec_ptr = hop->address; 01200 if ((cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) == 0) { 01201 if (hop->addrtype == ADDR_802_15_4_SHORT ) { 01202 hop->address[6] = hop->address[0]; 01203 hop->address[7] = hop->address[1]; 01204 memcpy(hop->address, ADDR_SHORT_ADR_SUFFIC, 6); 01205 } 01206 } 01207 } 01208 if ((cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) == 0) { 01209 //Remove old secondary priority and set new primary 01210 protocol_6lowpan_neighbor_priority_update(cur, sec_ptr, &buf->src_sa .address [8]); 01211 } 01212 // 01213 if (router->secondaty_hop) { 01214 memcpy(router->secondaty_hop, &router->default_hop, sizeof(nd_router_next_hop)); 01215 } 01216 icmp_nd_set_next_hop(&router->default_hop, &buf->src_sa ); 01217 } 01218 router->default_hop.LQI = buf->options .lqi ; 01219 } else if (new_router) { 01220 if (!router->secondaty_hop) { 01221 router->secondaty_hop = ns_dyn_mem_alloc(sizeof(nd_router_next_hop)); 01222 if (router->secondaty_hop) { 01223 router->secondaty_hop->LQI = 0; 01224 } 01225 } 01226 if (router->secondaty_hop) { 01227 if (router->secondaty_hop->LQI < buf->options .lqi ) { 01228 icmp_nd_set_next_hop(router->secondaty_hop, &buf->src_sa ); 01229 router->secondaty_hop->LQI = buf->options .lqi ; 01230 if ((cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) == 0) { 01231 //SET only new primary 01232 protocol_6lowpan_neighbor_priority_update(cur, 0, &buf->src_sa .address [8]); 01233 } 01234 } 01235 } 01236 } 01237 /* If waiting for an RS response */ 01238 /* XXX this accepts it even if stale - no abro version check. Problem? */ 01239 /* XXX this section below smells like stuff that should be outside this function */ 01240 if (router->nd_state == ND_RS_UNCAST || router->nd_state == ND_RS_MULTICAST) { 01241 /* Set uptodate to true so we accept data into our interface tables. 01242 * Consistent with previous behaviour, but is this what we want? 01243 */ 01244 uptodate = true; 01245 router->flags = ra_flags; 01246 icmp_nd_set_next_hop(&router->default_hop, &buf->src_sa ); 01247 router->default_hop.LQI = buf->options .lqi ; 01248 01249 icmp_nd_prefixs_parse(buf, router, cur); 01250 icmp_nd_context_parse(buf, router); 01251 01252 if (router->nd_state == ND_RS_MULTICAST) { 01253 if ((cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) == 0) { 01254 router->nd_timer = 1; 01255 } else { 01256 router->nd_timer = nd_params.rs_retry_interval_min; 01257 } 01258 tr_debug("RS MC Done"); 01259 } else { 01260 router->nd_timer = 1; 01261 tr_debug("RS Unicast Done"); 01262 mac_data_poll_protocol_poll_mode_decrement(cur); 01263 } 01264 router->ns_retry = nd_params.ns_retry_max; 01265 router->nd_state = ND_READY; 01266 router->nd_re_validate = (router_lifetime / 5) * 4; 01267 } 01268 } 01269 01270 if (uptodate) { 01271 router->abro_version_num = abro_ver_num; 01272 router->life_time = router_lifetime; 01273 } 01274 01275 return uptodate; 01276 } 01277 01278 /* This processes the 6CO for the interface itself - separate from the ABRO 01279 * multihop relay storage. 01280 * 01281 * 0 1 2 3 01282 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 01283 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 01284 * | Type | Length |Context Length | Res |C| CID | 01285 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 01286 * | Reserved | Valid Lifetime | 01287 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 01288 * . . 01289 * . Context Prefix . 01290 * . . 01291 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 01292 * 01293 */ 01294 void nd_ra_process_lowpan_context_option(protocol_interface_info_entry_t *cur, const uint8_t *opt) 01295 { 01296 uint8_t opt_len = opt[1]; 01297 uint8_t ctx_len = opt[2]; 01298 uint8_t cid_flags = opt[3]; 01299 uint16_t lifetime = common_read_16_bit(opt + 6); 01300 01301 if (ctx_len > 128 || ctx_len > (opt_len - 1) * 64) { 01302 return; 01303 } 01304 01305 lowpan_context_update(&cur->lowpan_contexts, cid_flags, lifetime, opt + 8, ctx_len, true); 01306 } 01307 #ifdef HAVE_6LOWPAN_ROUTER 01308 static void nd_ra_build(nd_router_t *cur, const uint8_t *address, protocol_interface_info_entry_t *cur_interface) 01309 { 01310 if (!(cur_interface->lowpan_info & INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY) || !icmp_nd_router_prefix_valid(cur)) { 01311 return; 01312 } 01313 01314 /* Base buffer size: RA Hdr = 12, ABRO = 24, MTU = up to 8, SLLAO = up to 16 */ 01315 uint16_t length = 12 + 24 + 8 + 16; 01316 length += 32 * ns_list_count(&cur->prefix_list); 01317 01318 ns_list_foreach(lowpan_context_t, context_ptr, &cur->context_list) { 01319 length += (context_ptr->length <= 64) ? 16 : 24; 01320 } 01321 01322 buffer_t *db = buffer_get(length); 01323 if (!db) { 01324 return; 01325 } else if (addr_interface_get_ll_address(cur_interface, db->src_sa .address , 0) != 0) { 01326 buffer_free(db); 01327 return; 01328 } 01329 db->src_sa .addr_type = ADDR_IPV6 ; 01330 01331 uint8_t *dptr = buffer_data_pointer(db); 01332 *dptr++ = cur_interface->adv_cur_hop_limit; 01333 *dptr++ = cur->flags; 01334 dptr = common_write_16_bit(cur->life_time, dptr); 01335 dptr = common_write_32_bit(cur_interface->adv_reachable_time, dptr); 01336 dptr = common_write_32_bit(cur_interface->adv_retrans_timer, dptr); 01337 01338 //SET ABRO 01339 *dptr++ = ICMPV6_OPT_AUTHORITATIVE_BORDER_RTR; 01340 *dptr++ = 3; //Len * 8 byte 01341 01342 dptr = common_write_16_bit((uint16_t)cur->abro_version_num, dptr); 01343 dptr = common_write_16_bit((uint16_t)(cur->abro_version_num >> 16), dptr); 01344 dptr = common_write_16_bit(0, dptr); 01345 memcpy(dptr, cur->border_router, 16); 01346 dptr += 16; 01347 //SET Prefixs 01348 dptr = icmpv6_write_prefix_option(&cur->prefix_list, dptr, 0, cur_interface); 01349 01350 ns_list_foreach(lowpan_context_t, context_ptr, &cur->context_list) { 01351 *dptr++ = ICMPV6_OPT_6LOWPAN_CONTEXT; 01352 *dptr++ = (context_ptr->length <= 64) ? 2 : 3; 01353 *dptr++ = context_ptr->length; 01354 *dptr++ = context_ptr->cid | (context_ptr->compression ? LOWPAN_CONTEXT_C : 0); 01355 dptr = common_write_16_bit(0, dptr); 01356 dptr = common_write_16_bit((context_ptr->lifetime + 599) / 600, dptr); 01357 length = (context_ptr->length <= 64) ? 8 : 16; 01358 memcpy(dptr, context_ptr->prefix, length); 01359 dptr += length; 01360 } 01361 01362 //MTU 01363 if (cur_interface->adv_link_mtu != 0) { 01364 dptr = icmpv6_write_mtu_option(cur_interface->adv_link_mtu, dptr); 01365 } 01366 01367 /* RFC 6775 mandates SLLAO in RA */ 01368 dptr = icmpv6_write_icmp_lla(cur_interface, dptr, ICMPV6_OPT_SRC_LL_ADDR, true, db->src_sa .address ); 01369 01370 if (address) { 01371 memcpy(db->dst_sa .address , address, 16); 01372 } else { 01373 memcpy(db->dst_sa .address , ADDR_LINK_LOCAL_ALL_NODES, 16); 01374 } 01375 buffer_data_end_set(db, dptr); 01376 01377 01378 db->dst_sa .addr_type = ADDR_IPV6 ; 01379 db->interface = cur_interface; 01380 db->info = (buffer_info_t)(B_FROM_ICMP | B_TO_ICMP | B_DIR_DOWN); 01381 db->options .type = ICMPV6_TYPE_INFO_RA; 01382 db->options .code = 0; 01383 db->options .hop_limit = 255; 01384 arm_net_protocol_packet_handler(db, cur_interface); 01385 01386 } 01387 01388 void nd_ra_build_by_abro(const uint8_t *abro, const uint8_t *dest, protocol_interface_info_entry_t *cur_interface) 01389 { 01390 ns_list_foreach(nd_router_t, cur, &nd_router_list) { 01391 if (addr_ipv6_equal(cur->border_router, abro)) { 01392 nd_ra_build(cur, dest, cur_interface); 01393 } 01394 } 01395 } 01396 01397 01398 void nd_trigger_ras_from_rs(const uint8_t *unicast_adr, protocol_interface_info_entry_t *cur_interface) 01399 { 01400 ns_list_foreach(nd_router_t, cur, &nd_router_list) { 01401 if (cur->nwk_id == cur_interface->nwk_id) { 01402 if (icmp_nd_router_prefix_valid(cur)) { 01403 //Allocate 01404 icmpv6_trigger_ra_from_rs(cur_interface, unicast_adr, cur->border_router); 01405 } 01406 } else { 01407 tr_error("BIND_CONFIRM FAIL!!"); 01408 } 01409 } 01410 } 01411 01412 void nd_ns_forward_timer_reset(uint8_t *root_adr) 01413 { 01414 ns_list_foreach(nd_router_t, cur, &nd_router_list) { 01415 if (memcmp(root_adr, cur->border_router, 16) == 0) { 01416 if (cur->ns_forward_timer) { 01417 cur->ns_forward_timer = 0; 01418 tr_warn("RX VALID DAC"); 01419 } 01420 break; 01421 } 01422 } 01423 } 01424 01425 static void nd_router_forward_timer(nd_router_t *cur, uint16_t ticks_update) 01426 { 01427 protocol_interface_info_entry_t *cur_interface; 01428 if (!(cur->ns_forward_timer)) { 01429 return; 01430 } 01431 01432 if (cur->ns_forward_timer > ticks_update) { 01433 cur->ns_forward_timer -= ticks_update; 01434 return; 01435 } 01436 01437 cur->ns_forward_timer = 0; 01438 cur_interface = protocol_stack_interface_info_get(cur->nwk_id); 01439 if (cur_interface) { 01440 if (cur->nd_re_validate > 10) { 01441 tr_debug("TRIG NS/ND"); 01442 cur->nd_timer = 1; 01443 cur->nd_re_validate = 1; 01444 } 01445 if (cur_interface->if_6lowpan_dad_process.active == false) { 01446 nd_ns_trig(cur, cur_interface); 01447 } 01448 } 01449 } 01450 01451 ipv6_ra_timing_t *nd_ra_timing(const uint8_t abro[16]) 01452 { 01453 ns_list_foreach(nd_router_t, cur, &nd_router_list) { 01454 if (addr_ipv6_equal(abro, cur->border_router)) { 01455 return &cur->ra_timing; 01456 } 01457 } 01458 01459 return NULL; 01460 } 01461 01462 static nd_router_t *nd_router_object_scan_by_prefix(const uint8_t *ptr, nwk_interface_id nwk_id) 01463 { 01464 ns_list_foreach(nd_router_t, cur, &nd_router_list) { 01465 if (cur->nwk_id == nwk_id) { 01466 if (icmpv6_prefix_compare(&cur->prefix_list, ptr, 64)) { 01467 return cur; 01468 } 01469 } 01470 } 01471 01472 return NULL; 01473 } 01474 01475 #endif 01476 01477 void gp_address_add_to_end(gp_ipv6_address_list_t *list, const uint8_t address[static 16]) 01478 { 01479 gp_ipv6_address_entry_t *new_entry; 01480 01481 ns_list_foreach(gp_ipv6_address_entry_t, cur, list) { 01482 if (memcmp(cur->address, address, 16) == 0) { 01483 return; 01484 } 01485 } 01486 01487 new_entry = ns_dyn_mem_alloc(sizeof(gp_ipv6_address_entry_t)); 01488 if (!new_entry) { 01489 tr_warn("No heap for New Address"); 01490 return; 01491 } 01492 01493 memcpy(new_entry->address, address, 16); 01494 ns_list_add_to_end(list, new_entry); 01495 } 01496 01497 /* Returns 1 if the router object has been removed */ 01498 static uint8_t nd_router_ready_timer(nd_router_t *cur, protocol_interface_info_entry_t *cur_interface, uint16_t ticks_update) 01499 { 01500 if (!cur->nd_timer) { 01501 return 0; 01502 } 01503 01504 if (cur->nd_timer > ticks_update) { 01505 cur->nd_timer -= ticks_update; 01506 return 0; 01507 } 01508 01509 //Take out last remaing time from ticks 01510 ticks_update -= cur->nd_timer; 01511 uint16_t updated_seconds = 1; 01512 cur->nd_timer = 10; 01513 if (ticks_update) { 01514 updated_seconds += (ticks_update / 10); 01515 //Set Next second based on over based time 01516 cur->nd_timer -= (ticks_update % 10); 01517 } 01518 01519 if (icmp_nd_router_prefix_ttl_update(cur, cur_interface, updated_seconds)) { 01520 return 1; 01521 } 01522 01523 //Update seconds 01524 icmp_nd_router_context_ttl_update(cur, updated_seconds); 01525 01526 if (!cur->nd_re_validate) { 01527 return 0; 01528 } 01529 01530 if (cur->nd_re_validate > updated_seconds) { 01531 cur->nd_re_validate -= updated_seconds; 01532 //tr_debug("NDR:Tick Update %u", cur->nd_re_validate); 01533 return 0; 01534 } 01535 01536 if (cur->nd_state == ND_READY) { 01537 tr_debug("RE ND Process: RS Unicast!"); 01538 cur->ns_retry = nd_params.rs_retry_max; 01539 cur->nd_state = ND_RS_UNCAST; 01540 set_power_state(ICMP_ACTIVE); 01541 cur->nd_timer = 1; 01542 cur->nd_bootstrap_tick = (nd_base_tick - 1); 01543 if (cur_interface->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE) { 01544 mac_data_poll_init_protocol_poll(cur_interface); 01545 } 01546 nd_router_bootstrap_timer(cur, cur_interface, 1); 01547 } else { /* ND_BR_READY */ 01548 nd_border_router_setup_refresh(cur->nwk_id, true); 01549 tr_debug("ND BR refresh ABRO"); 01550 cur->nd_re_validate = (cur->life_time / 4) * 3; 01551 icmpv6_restart_router_advertisements(cur_interface, cur->border_router); 01552 } 01553 return 0; 01554 } 01555 01556 /* Returns 1 if the router object has been removed, or we want no further processing on this tick */ 01557 static uint8_t nd_router_bootstrap_timer(nd_router_t *cur, protocol_interface_info_entry_t *cur_interface, uint16_t ticks) 01558 { 01559 uint16_t scaled_ticks; 01560 /* 01561 * nd_timer is scaled by nd_base_tick during the discovery states, 01562 * to allow API to slow down the ND process. Note we count up and test 01563 * inequality, just in case someone decides to change nd_base_tick on 01564 * the fly. 01565 */ 01566 if (cur->nd_bootstrap_tick + ticks < nd_base_tick) { 01567 cur->nd_bootstrap_tick += ticks; 01568 return 0; 01569 } 01570 01571 //Take off scaled ticks 01572 ticks -= (nd_base_tick - cur->nd_bootstrap_tick); 01573 01574 scaled_ticks = 1 + (ticks / nd_base_tick); 01575 01576 cur->nd_bootstrap_tick = 0 + (ticks % nd_base_tick); 01577 01578 if (!cur->nd_timer) { 01579 tr_debug("NDB:Tick Update fail %u", scaled_ticks); 01580 return 0; 01581 } 01582 01583 01584 if (cur->nd_timer > scaled_ticks) { 01585 cur->nd_timer -= scaled_ticks; 01586 return 0; 01587 } 01588 01589 switch (cur->nd_state) { 01590 01591 case ND_RS_UNCAST: 01592 case ND_RS_MULTICAST: 01593 if (cur->ns_retry) { 01594 if (nd_rs_build(cur->nd_state == ND_RS_UNCAST ? cur : NULL, cur_interface)) { 01595 cur->nd_timer = nd_params.rs_retry_interval_min; 01596 cur->nd_timer += randLIB_get_16bit() & nd_params.timer_random_max; 01597 cur->ns_retry--; 01598 tr_debug(cur->nd_state == ND_RS_UNCAST ? "RS" : "RS+"); 01599 } else { 01600 cur->nd_timer = 2; 01601 } 01602 } else { 01603 //ND FAIL 01604 if (cur->nd_state == ND_RS_UNCAST) { 01605 cur->ns_retry = nd_params.rs_retry_max; 01606 cur->nd_state = ND_RS_MULTICAST; 01607 cur->nd_timer = 1; 01608 } else { 01609 //RS UNICAST Fail 01610 /*if (rpl_object_poisons() == 0) ??? */ { 01611 protocol_6lowpan_bootstrap_re_start(cur_interface); 01612 } 01613 return 1; 01614 } 01615 } 01616 break; 01617 01618 case ND_READY: 01619 case ND_BR_READY: 01620 /* Not called for these states - put in to suppress GCC warning */ 01621 break; 01622 } 01623 01624 return 0; 01625 } 01626 01627 01628 void nd_object_timer(protocol_interface_info_entry_t *cur_interface, uint16_t ticks_update) 01629 { 01630 ns_list_foreach_safe(nd_router_t, cur, &nd_router_list) { 01631 /* This may nd_router_remove(cur), so need to use safe loop */ 01632 if (cur_interface->nwk_id == cur->nwk_id) { 01633 01634 protocol_6lowpan_link_advertise_handle(cur, cur_interface, ticks_update); 01635 01636 if (cur->nd_state != ND_BR_READY) { 01637 nd_router_forward_timer(cur, ticks_update); 01638 } 01639 01640 if (nd_is_ready_state(cur->nd_state)) { 01641 nd_router_ready_timer(cur, cur_interface, ticks_update); 01642 } else { 01643 nd_router_bootstrap_timer(cur, cur_interface, ticks_update); 01644 } 01645 return; 01646 } 01647 } 01648 } 01649 01650 uint32_t nd_object_time_to_next_nd_reg(void) 01651 { 01652 uint32_t ret_val = 0; 01653 ns_list_foreach(nd_router_t, cur, &nd_router_list) { 01654 if (cur->nd_state == ND_READY) { 01655 ret_val = cur->nd_re_validate; 01656 ret_val++; 01657 ret_val *= 1000; 01658 /* XXX surely this should find the shortest, not the first? */ 01659 break; 01660 } 01661 } 01662 return ret_val; 01663 } 01664 01665 uint8_t nd_prefix_dst_check(uint8_t *ptr) 01666 { 01667 ns_list_foreach(nd_router_t, cur, &nd_router_list) { 01668 if (icmpv6_prefix_compare(&cur->prefix_list, ptr, 64)) { 01669 return 1; 01670 } 01671 } 01672 return 0; 01673 } 01674 01675 01676 int8_t nd_parent_loose_indcate(uint8_t *neighbor_address, protocol_interface_info_entry_t *cur_interface) 01677 { 01678 int8_t ret_val = -1; 01679 addrtype_t adr_type = ADDR_802_15_4_LONG ; 01680 uint8_t *adr_ptr = neighbor_address; 01681 nd_router_next_hop *hop; 01682 uint8_t compare_len = 8; 01683 01684 ns_list_foreach(nd_router_t, cur, &nd_router_list) { 01685 if (!(cur_interface->lowpan_info & INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY)) { 01686 continue; 01687 } 01688 01689 hop = &cur->default_hop; 01690 if (memcmp(neighbor_address, ADDR_SHORT_ADR_SUFFIC, 6) == 0) { 01691 adr_ptr += 6; 01692 adr_type = ADDR_802_15_4_SHORT ; 01693 compare_len = 2; 01694 } 01695 if (hop->addrtype == adr_type) { 01696 if (memcmp(hop->address, adr_ptr, compare_len) == 0) { 01697 tr_debug("ND Primary Parent Lost"); 01698 01699 if (cur->secondaty_hop == 0) { 01700 ret_val = -1; 01701 } else { 01702 ret_val = 0; 01703 tr_debug("Swap Secondary to primary"); 01704 memcpy(hop, cur->secondaty_hop, sizeof(nd_router_next_hop)); 01705 tr_debug("Trig NS/NA with new parent"); 01706 if (cur->nd_state == ND_READY) { 01707 cur->nd_re_validate = 1; 01708 if (cur_interface->if_6lowpan_dad_process.active == false) { 01709 nd_ns_trig(cur, cur_interface); 01710 } 01711 } 01712 ns_dyn_mem_free(cur->secondaty_hop); 01713 cur->secondaty_hop = 0; 01714 } 01715 return ret_val; 01716 } 01717 } else if (cur->secondaty_hop) { 01718 hop = cur->secondaty_hop; 01719 if (hop->addrtype == adr_type) { 01720 if (memcmp(hop->address, adr_ptr, compare_len) == 0) { 01721 tr_debug("ND Secondary Parent Lost"); 01722 ns_dyn_mem_free(cur->secondaty_hop); 01723 cur->secondaty_hop = 0; 01724 return 0; 01725 } 01726 } 01727 } 01728 } 01729 return -1; 01730 } 01731 01732 nd_router_t *nd_get_object_by_nwk_id(nwk_interface_id nwk_id) 01733 { 01734 ns_list_foreach(nd_router_t, cur, &nd_router_list) { 01735 if (cur->nwk_id == nwk_id) { 01736 return cur; 01737 } 01738 } 01739 01740 return 0; 01741 } 01742 01743 nd_router_t *nd_get_pana_address(void) 01744 { 01745 return ns_list_get_first(&nd_router_list); 01746 } 01747 01748 void nd_6lowpan_set_radv_params(protocol_interface_info_entry_t *cur_interface) 01749 { 01750 #ifndef NO_RADV_TX 01751 cur_interface->max_ra_delay_time = 20; 01752 cur_interface->min_delay_between_ras = 100; 01753 cur_interface->rtr_adv_unicast_to_rs = true; 01754 cur_interface->adv_cur_hop_limit = nd_params.ra_cur_hop_limit; 01755 cur_interface->adv_link_mtu = nd_params.ra_link_mtu; 01756 cur_interface->adv_reachable_time = nd_params.ra_reachable_time; 01757 cur_interface->adv_retrans_timer = nd_params.ra_retrans_timer; 01758 cur_interface->max_initial_rtr_adv_interval = nd_params.ra_interval_min; 01759 cur_interface->max_initial_rtr_advertisements = nd_params.ra_transmits; 01760 #endif 01761 } 01762 #endif // HAVE_6LOWPAN_ND 01763
Generated on Tue Jul 12 2022 13:54:37 by
1.7.2