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.
nd_router_object.c
00001 /* 00002 * Copyright (c) 2013-2018, 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 } 00724 else 00725 #endif 00726 { 00727 icmp_nd_set_nd_def_router_address(router, cur); 00728 } 00729 00730 aro.status = ARO_SUCCESS; 00731 aro.present = true; 00732 aro.lifetime = (cur->life_time / 60) + 1; 00733 memcpy(aro.eui64, cur_interface->mac, 8); 00734 00735 buf = icmpv6_build_ns(cur_interface, router, address_ptr, true, false, &aro); 00736 protocol_push(buf); 00737 } 00738 00739 /* RFC 6775 Duplicate Address Request/Confirmation packets 00740 * 00741 * 0 1 2 3 00742 * 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 00743 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00744 * | Type | Code | Checksum | 00745 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00746 * | Status | Reserved | Registration Lifetime | 00747 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00748 * | | 00749 * + EUI-64 + 00750 * | | 00751 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00752 * | | 00753 * + + 00754 * | | 00755 * + Registered Address + 00756 * | | 00757 * + + 00758 * | | 00759 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00760 * 00761 * (and 8.2.1 implies this is can be followed by options, although 00762 * none are defined). 00763 */ 00764 #ifdef HAVE_6LOWPAN_ROUTER 00765 static bool nd_dar_dac_valid(buffer_t *buf) 00766 { 00767 const uint8_t *dptr = buffer_data_pointer(buf); 00768 00769 if (buf->options .code != 0) { 00770 return false; 00771 } 00772 00773 if (!icmpv6_options_well_formed_in_buffer(buf, 28)) { 00774 return false; 00775 } 00776 00777 if (addr_is_ipv6_multicast(dptr + 12)) { 00778 return false; 00779 } 00780 00781 if (addr_is_ipv6_unspecified(buf->src_sa .address ) || 00782 addr_is_ipv6_multicast(buf->src_sa .address )) { 00783 return false; 00784 } 00785 00786 return true; 00787 } 00788 #endif 00789 00790 buffer_t *nd_dar_parse(buffer_t *buf, protocol_interface_info_entry_t *cur_interface) 00791 { 00792 #if defined WHITEBOARD && defined HAVE_6LOWPAN_BORDER_ROUTER 00793 uint8_t *dptr = buffer_data_pointer(buf); 00794 buffer_t *retbuf; 00795 uint8_t status; 00796 uint16_t lifetime; 00797 const uint8_t *eui64; 00798 00799 if (!nd_dar_dac_valid(buf)) { 00800 goto drop; 00801 } 00802 00803 status = *dptr; 00804 dptr += 2; 00805 lifetime = common_read_16_bit(dptr); 00806 dptr += 2; 00807 00808 if (status != ARO_SUCCESS) { 00809 goto drop; 00810 } 00811 00812 whiteboard_entry_t *wb; 00813 00814 /* EUI-64 */ 00815 eui64 = dptr; 00816 dptr += 8; 00817 tr_debug("DAR adr: %s, from %s", trace_ipv6(dptr), trace_ipv6(buf->src_sa .address )); 00818 00819 //SET White board 00820 wb = whiteboard_table_update(dptr, eui64, &status); 00821 if (wb && status == ARO_SUCCESS) { 00822 memcpy(wb->address, dptr, 16); 00823 memcpy(wb->eui64, eui64, 8); 00824 wb->interface_index = cur_interface->id; 00825 wb->ttl = UINT24_C(60) * lifetime; 00826 } 00827 00828 retbuf = icmpv6_build_dad(cur_interface, NULL, ICMPV6_TYPE_INFO_DAC, buf->src_sa .address , eui64, dptr, status, lifetime); 00829 if (retbuf) { 00830 buffer_free(buf); 00831 return retbuf; 00832 } 00833 00834 drop: 00835 #endif 00836 00837 return buffer_free(buf); 00838 } 00839 00840 #ifdef HAVE_6LOWPAN_ROUTER 00841 static void nd_update_registration(protocol_interface_info_entry_t *cur_interface, ipv6_neighbour_t *neigh, const aro_t *aro) 00842 { 00843 /* We are about to send an ARO response - update our Neighbour Cache accordingly */ 00844 if (aro->status == ARO_SUCCESS && aro->lifetime != 0) { 00845 neigh->type = IP_NEIGHBOUR_REGISTERED; 00846 neigh->lifetime = aro->lifetime * UINT32_C(60); 00847 ipv6_neighbour_set_state(&cur_interface->ipv6_neighbour_cache, neigh, IP_NEIGHBOUR_STALE); 00848 /* Register with 2 seconds off the lifetime - don't want the NCE to expire before the route */ 00849 ipv6_route_add(neigh->ip_address, 128, cur_interface->id, NULL, ROUTE_ARO, neigh->lifetime - 2, 0); 00850 00851 /* We need to know peer is a host before publishing - this needs MLE. Not yet established 00852 * what to do without MLE - might need special external/non-external prioritisation at root. 00853 * This "publish for RFD" rule comes from ZigBee IP. 00854 */ 00855 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 ); 00856 00857 if (entry && !entry->ffd_device ) { 00858 rpl_control_publish_host_address(protocol_6lowpan_rpl_domain, neigh->ip_address, neigh->lifetime); 00859 } 00860 protocol_6lowpan_neighbor_address_state_synch(cur_interface, aro->eui64, neigh->ip_address + 8); 00861 00862 } else { 00863 /* Um, no - can't transmit response if we remove NCE now! */ 00864 //ipv6_neighbour_entry_remove(&cur_interface->ipv6_neighbour_cache, neigh); 00865 neigh->type = IP_NEIGHBOUR_TENTATIVE; 00866 neigh->lifetime = 2; 00867 ipv6_neighbour_set_state(&cur_interface->ipv6_neighbour_cache, neigh, IP_NEIGHBOUR_STALE); 00868 ipv6_route_add(neigh->ip_address, 128, cur_interface->id, NULL, ROUTE_ARO, 4, 0); 00869 rpl_control_unpublish_address(protocol_6lowpan_rpl_domain, neigh->ip_address); 00870 } 00871 } 00872 00873 void nd_remove_registration(protocol_interface_info_entry_t *cur_interface, addrtype_t ll_type, const uint8_t *ll_address) 00874 { 00875 00876 ns_list_foreach_safe(ipv6_neighbour_t, cur, &cur_interface->ipv6_neighbour_cache.list) 00877 { 00878 if ((cur->type == IP_NEIGHBOUR_REGISTERED 00879 || cur->type == IP_NEIGHBOUR_TENTATIVE) 00880 && ipv6_neighbour_ll_addr_match(cur, ll_type, ll_address)) { 00881 ipv6_route_delete(cur->ip_address, 128, cur_interface->id, NULL, 00882 ROUTE_ARO); 00883 ipv6_neighbour_entry_remove(&cur_interface->ipv6_neighbour_cache, 00884 cur); 00885 } 00886 } 00887 } 00888 00889 /* Process ICMP Neighbor Solicitation (RFC 4861 + RFC 6775) ARO. */ 00890 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) 00891 { 00892 /* Ignore any ARO if source is link-local */ 00893 if (addr_is_ipv6_link_local(src_addr)) { 00894 return true; /* Transmit NA, without ARO */ 00895 } 00896 00897 /* If we can't parse the SLLAO, then act as if no SLLAO: ignore ARO */ 00898 sockaddr_t ll_addr; 00899 if (!cur_interface->if_llao_parse(cur_interface, slla_opt, &ll_addr)) { 00900 return true; /* Transmit NA, without ARO */ 00901 } 00902 00903 /* 00904 * 0 1 2 3 00905 * 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 00906 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00907 * | Type = 33 | Length = 2 | Status | Reserved | 00908 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00909 * | Reserved | Registration Lifetime | 00910 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00911 * | | 00912 * + EUI-64 + 00913 * | | 00914 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00915 */ 00916 /* icmpv6_ns_handler has already checked incoming status == 0 */ 00917 aro_out->lifetime = common_read_16_bit(aro_opt + 6); 00918 memcpy(aro_out->eui64, aro_opt + 8, 8); 00919 00920 /* Check if we are already using this address ourself */ 00921 if (addr_interface_address_compare(cur_interface, src_addr) == 0) { 00922 aro_out->present = true; 00923 aro_out->status = ARO_DUPLICATE; 00924 return true; 00925 } 00926 00927 /* TODO - check hard upper limit on registrations? */ 00928 00929 /* We need to have entry in the Neighbour Cache */ 00930 ipv6_neighbour_t *neigh = ipv6_neighbour_lookup_or_create(&cur_interface->ipv6_neighbour_cache, src_addr); 00931 if (!neigh) { 00932 aro_out->present = true; 00933 aro_out->status = ARO_FULL; 00934 return true; 00935 } 00936 00937 uint8_t *nce_eui64 = ipv6_neighbour_eui64(&cur_interface->ipv6_neighbour_cache, neigh); 00938 if (neigh->state != IP_NEIGHBOUR_NEW) { 00939 switch (neigh->type) { 00940 case IP_NEIGHBOUR_TENTATIVE: 00941 /* Is zero EUI-64 still possible? */ 00942 if (memcmp(nce_eui64, aro_out->eui64, 8) && memcmp(nce_eui64, ADDR_EUI64_ZERO, 8)) { 00943 /* Have a Tentative NCE with different EUI-64 - ignore NS; two 00944 * people trying to register at once. One should retry. 00945 */ 00946 return false; 00947 } 00948 break; 00949 case IP_NEIGHBOUR_REGISTERED: 00950 if (memcmp(nce_eui64, aro_out->eui64, 8)) { 00951 /* Already registered with different EUI-64 - duplicate */ 00952 aro_out->present = true; 00953 aro_out->status = ARO_DUPLICATE; 00954 return true; 00955 } 00956 break; 00957 case IP_NEIGHBOUR_GARBAGE_COLLECTIBLE: 00958 break; 00959 } 00960 } 00961 00962 if (neigh->type != IP_NEIGHBOUR_REGISTERED) { 00963 neigh->type = IP_NEIGHBOUR_TENTATIVE; 00964 neigh->lifetime = TENTATIVE_NCE_LIFETIME; 00965 memcpy(nce_eui64, aro_out->eui64, 8); 00966 } 00967 00968 /* Set the LL address, ensure it's marked STALE */ 00969 ipv6_neighbour_entry_update_unsolicited(&cur_interface->ipv6_neighbour_cache, neigh, ll_addr.addr_type , ll_addr.address ); 00970 ipv6_neighbour_set_state(&cur_interface->ipv6_neighbour_cache, neigh, IP_NEIGHBOUR_STALE); 00971 if (ws_info(cur_interface)) { 00972 aro_out->status = ARO_SUCCESS; 00973 aro_out->present = true; 00974 // Todo: this might not be needed... 00975 nd_update_registration(cur_interface, neigh, aro_out); 00976 return true; 00977 } 00978 if (cur_interface->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER || nd_params.multihop_dad == false) { 00979 if (cur_interface->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { 00980 whiteboard_entry_t *wb; 00981 wb = whiteboard_table_update(src_addr, aro_out->eui64, &aro_out->status); 00982 if (wb) { 00983 if (aro_out->status == ARO_SUCCESS) { 00984 memcpy(wb->address, src_addr, 16); 00985 memcpy(wb->eui64, aro_out->eui64, 8); 00986 wb->interface_index = cur_interface->id; 00987 wb->ttl = 50000;//life_time; 00988 } 00989 } else { 00990 tr_warn("white Board Registry fail"); 00991 aro_out->status = ARO_FULL; 00992 goto RESPONSE; 00993 } 00994 } 00995 00996 RESPONSE: 00997 aro_out->present = true; 00998 nd_update_registration(cur_interface, neigh, aro_out); 00999 return true; /* Transmit NA */ 01000 } else { /* Non-border router and multihop DAD: relay as DAR to Border Router */ 01001 nd_router_t *nd_router_obj = 0; 01002 01003 nd_router_obj = nd_router_object_scan_by_prefix(src_addr, cur_interface->nwk_id); 01004 if (!nd_router_obj) { 01005 /* Don't know where to send this. Do we say "yay" or "nay"? */ 01006 /* For now, ignore ARO, as with old code; don't set aro_out.present */ 01007 return true; 01008 } 01009 01010 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); 01011 if (!buf) { 01012 return false; /* Failed to build DAR - drop NS */ 01013 } 01014 01015 tr_debug("RX:NS --> TX DAR to Root"); 01016 protocol_push(buf); 01017 if (nd_router_obj->ns_forward_timer == 0) { 01018 nd_router_obj->ns_forward_timer = nd_params.ns_forward_timeout; 01019 } 01020 01021 return false; /* Tell ns_handler to not transmit now */ 01022 } 01023 } 01024 01025 buffer_t *nd_dac_handler(buffer_t *buf, protocol_interface_info_entry_t *cur) 01026 { 01027 uint8_t *dptr, target_address[16], *reg_address; 01028 aro_t aro; 01029 01030 dptr = buffer_data_pointer(buf); 01031 01032 if (!nd_dar_dac_valid(buf)) { 01033 return buffer_free(buf); 01034 } 01035 01036 nd_ns_forward_timer_reset(buf->src_sa .address ); 01037 01038 aro.status = *dptr; 01039 dptr += 2; 01040 aro.lifetime = common_read_16_bit(dptr); 01041 dptr += 2; 01042 /* EUI-64 */ 01043 memcpy(aro.eui64, dptr, 8); 01044 dptr += 8; 01045 reg_address = dptr; 01046 dptr += 16; 01047 01048 ipv6_neighbour_t *neigh = ipv6_neighbour_lookup(&cur->ipv6_neighbour_cache, reg_address); 01049 if (!neigh || neigh->type == IP_NEIGHBOUR_GARBAGE_COLLECTIBLE || memcmp(ipv6_neighbour_eui64(&cur->ipv6_neighbour_cache, neigh), aro.eui64, 8)) { 01050 return buffer_free(buf); 01051 } 01052 01053 nd_update_registration(cur, neigh, &aro); 01054 01055 /* RFC 6775 has a bit of a hole here - what's the Target Address? */ 01056 /* It's not in the DAC. We didn't record locally when we sent the DAR */ 01057 /* I guess it's logical that we use a link-local address. We break */ 01058 /* RFC 4861 by responding "solicited", but not to the NS Target... */ 01059 /* However, my reading of RFC 4861 says that the receiver should do */ 01060 /* the right thing. Only problem is that what if they really did want */ 01061 /* to do a NUD probe for our GP addr, but included the ARO by mistake? */ 01062 if (addr_interface_get_ll_address(cur, target_address, 0)) { 01063 return buffer_free(buf); 01064 } 01065 01066 /* NA builder will send it to the address in the buffer's source */ 01067 memcpy(buf->src_sa .address , reg_address, 16); 01068 01069 buffer_t *na_buf = icmpv6_build_na(cur, true, true, false, target_address, &aro, buf->src_sa .address ); 01070 01071 buffer_free(buf); 01072 01073 return na_buf; 01074 } 01075 #endif // HAVE_6LOWPAN_ROUTER 01076 01077 /* Original ABRO-based all-in-one parser. This needs some rework to separate ABRO-related and unrelated bits */ 01078 /* Returns "false" if ABRO suggested it was a stale message, so not worth handling in the normal code */ 01079 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) 01080 { 01081 nd_router_t *router; 01082 uint32_t abro_ver_num; 01083 uint16_t temp16; 01084 bool uptodate = false; 01085 01086 /* XXX this is really a 32-bit number these days */ 01087 temp16 = common_read_16_bit(dptr); 01088 abro_ver_num = temp16; 01089 dptr += 2; 01090 temp16 = common_read_16_bit(dptr); 01091 //SET MSB bytes to 32-bit 01092 abro_ver_num |= ((uint32_t)temp16 << 16); 01093 01094 dptr += 4; 01095 //If Border Router boot is state 01096 01097 if(cur->border_router_setup) 01098 { 01099 if(memcmp(dptr, cur->border_router_setup->border_router_gp_adr, 16) == 0) 01100 { 01101 if (cur->border_router_setup->initActive) { 01102 //save New Context 01103 if (common_serial_number_greater_32(abro_ver_num, cur->border_router_setup->nd_border_router_configure->abro_version_num)) { 01104 cur->border_router_setup->initActive = false; 01105 cur->border_router_setup->nd_border_router_configure->abro_version_num = (abro_ver_num + 0x00010000); 01106 cur->border_router_setup->nd_nwk->abro_version_num = (abro_ver_num + 0x00010000); 01107 } else if(abro_ver_num == cur->border_router_setup->nd_border_router_configure->abro_version_num) { 01108 01109 cur->border_router_setup->initActive = false; 01110 cur->border_router_setup->nd_border_router_configure->abro_version_num = (abro_ver_num + 0x00010000); 01111 cur->border_router_setup->nd_nwk->abro_version_num = (abro_ver_num + 0x00010000); 01112 } 01113 } 01114 return true; 01115 } 01116 return false; 01117 } 01118 01119 router = icmp_nd_router_object_get(dptr, buf->interface ->nwk_id); 01120 if (!router) { 01121 return true; 01122 } 01123 01124 if (router->default_hop.addrtype == ADDR_NONE ) { 01125 tr_debug("Create ND version"); 01126 01127 router->flags = ra_flags; 01128 01129 uptodate = true; 01130 icmp_nd_set_next_hop(&router->default_hop, &buf->src_sa ); 01131 router->default_hop.LQI = buf->options .lqi ; 01132 01133 icmp_nd_prefixs_parse(buf, router, cur); 01134 icmp_nd_context_parse(buf, router); 01135 01136 if ((cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) == 0) { 01137 //SET OnlY primary 01138 uint8_t address[8]; 01139 if (router->default_hop.addrtype == ADDR_802_15_4_SHORT ) { 01140 address[6] = router->default_hop.address[0]; 01141 address[7] = router->default_hop.address[1]; 01142 memcpy(address, ADDR_SHORT_ADR_SUFFIC, 6); 01143 } else { 01144 memcpy(address, router->default_hop.address, 8); 01145 } 01146 protocol_6lowpan_neighbor_priority_update(cur, NULL, address); 01147 } 01148 router->nd_state = ND_READY; 01149 router->nd_re_validate = (router_lifetime / 5) * 4; 01150 router->nd_timer = 10; 01151 } else { 01152 bool new_router = icmp_nd_compare_to_def_next_hop(&router->default_hop, &buf->src_sa ); 01153 01154 if (abro_ver_num == router->abro_version_num) { 01155 /* Up-to-date for host processing, but don't necessarily process for multi-hop relaying */ 01156 uptodate = true; 01157 } 01158 01159 /* XXX this is really a 32-bit number these days */ 01160 if (common_serial_number_greater_32(abro_ver_num, router->abro_version_num)) { 01161 uint32_t diff_update; 01162 diff_update = (abro_ver_num - router->abro_version_num); 01163 uptodate = true; 01164 01165 //uprouter_info=1; 01166 if(diff_update >= 0x00010000) 01167 { 01168 tr_debug("Border Router Boot Trig NS"); 01169 router->trig_address_reg = true; 01170 } else { 01171 tr_debug("Next num"); 01172 } 01173 01174 icmpv6_prefix_list_free(&router->prefix_list); 01175 01176 lowpan_context_list_free(&router->context_list); 01177 01178 icmp_nd_prefixs_parse(buf, router, cur); 01179 router->trig_address_reg = false; 01180 icmp_nd_context_parse(buf, router); 01181 icmpv6_restart_router_advertisements(cur, router->border_router); 01182 } else if (router->default_hop.LQI < buf->options .lqi ) { 01183 /* XXX another zero-hysteresis parent swap */ 01184 if (new_router) { 01185 uint8_t *sec_ptr = NULL; 01186 if (router->secondaty_hop == 0) { 01187 router->secondaty_hop = ns_dyn_mem_alloc(sizeof(nd_router_next_hop)); 01188 } else { 01189 nd_router_next_hop *hop = router->secondaty_hop; 01190 sec_ptr = hop->address; 01191 if ((cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) == 0) { 01192 if (hop->addrtype == ADDR_802_15_4_SHORT ) { 01193 hop->address[6] = hop->address[0]; 01194 hop->address[7] = hop->address[1]; 01195 memcpy(hop->address, ADDR_SHORT_ADR_SUFFIC, 6); 01196 } 01197 } 01198 } 01199 if ((cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) == 0) { 01200 //Remove old secondary priority and set new primary 01201 protocol_6lowpan_neighbor_priority_update(cur, sec_ptr, &buf->src_sa .address [8]); 01202 } 01203 // 01204 if (router->secondaty_hop) { 01205 memcpy(router->secondaty_hop, &router->default_hop, sizeof(nd_router_next_hop)); 01206 } 01207 icmp_nd_set_next_hop(&router->default_hop, &buf->src_sa ); 01208 } 01209 router->default_hop.LQI = buf->options .lqi ; 01210 } else if (new_router) { 01211 if (!router->secondaty_hop) { 01212 router->secondaty_hop = ns_dyn_mem_alloc(sizeof(nd_router_next_hop)); 01213 if (router->secondaty_hop) { 01214 router->secondaty_hop->LQI = 0; 01215 } 01216 } 01217 if (router->secondaty_hop) { 01218 if (router->secondaty_hop->LQI < buf->options .lqi ) { 01219 icmp_nd_set_next_hop(router->secondaty_hop, &buf->src_sa ); 01220 router->secondaty_hop->LQI = buf->options .lqi ; 01221 if ((cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) == 0) { 01222 //SET only new primary 01223 protocol_6lowpan_neighbor_priority_update(cur, 0, &buf->src_sa .address [8]); 01224 } 01225 } 01226 } 01227 } 01228 /* If waiting for an RS response */ 01229 /* XXX this accepts it even if stale - no abro version check. Problem? */ 01230 /* XXX this section below smells like stuff that should be outside this function */ 01231 if (router->nd_state == ND_RS_UNCAST || router->nd_state == ND_RS_MULTICAST) { 01232 /* Set uptodate to true so we accept data into our interface tables. 01233 * Consistent with previous behaviour, but is this what we want? 01234 */ 01235 uptodate = true; 01236 router->flags = ra_flags; 01237 icmp_nd_set_next_hop(&router->default_hop, &buf->src_sa ); 01238 router->default_hop.LQI = buf->options .lqi ; 01239 01240 icmp_nd_prefixs_parse(buf, router, cur); 01241 icmp_nd_context_parse(buf, router); 01242 01243 if (router->nd_state == ND_RS_MULTICAST) { 01244 if ((cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) == 0) { 01245 router->nd_timer = 1; 01246 } else { 01247 router->nd_timer = nd_params.rs_retry_interval_min; 01248 } 01249 tr_debug("RS MC Done"); 01250 } else { 01251 router->nd_timer = 1; 01252 tr_debug("RS Unicast Done"); 01253 mac_data_poll_protocol_poll_mode_decrement(cur); 01254 } 01255 router->ns_retry = nd_params.ns_retry_max; 01256 router->nd_state = ND_READY; 01257 router->nd_re_validate = (router_lifetime / 5) * 4; 01258 } 01259 } 01260 01261 if(uptodate) 01262 { 01263 router->abro_version_num = abro_ver_num; 01264 router->life_time = router_lifetime; 01265 } 01266 01267 return uptodate; 01268 } 01269 01270 /* This processes the 6CO for the interface itself - separate from the ABRO 01271 * multihop relay storage. 01272 * 01273 * 0 1 2 3 01274 * 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 01275 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 01276 * | Type | Length |Context Length | Res |C| CID | 01277 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 01278 * | Reserved | Valid Lifetime | 01279 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 01280 * . . 01281 * . Context Prefix . 01282 * . . 01283 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 01284 * 01285 */ 01286 void nd_ra_process_lowpan_context_option(protocol_interface_info_entry_t *cur, const uint8_t *opt) 01287 { 01288 uint8_t opt_len = opt[1]; 01289 uint8_t ctx_len = opt[2]; 01290 uint8_t cid_flags = opt[3]; 01291 uint16_t lifetime = common_read_16_bit(opt + 6); 01292 01293 if (ctx_len > 128 || ctx_len > (opt_len - 1) * 64) { 01294 return; 01295 } 01296 01297 lowpan_context_update(&cur->lowpan_contexts, cid_flags, lifetime, opt + 8, ctx_len, true); 01298 } 01299 #ifdef HAVE_6LOWPAN_ROUTER 01300 static void nd_ra_build(nd_router_t *cur, const uint8_t *address, protocol_interface_info_entry_t *cur_interface) 01301 { 01302 if (!(cur_interface->lowpan_info & INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY) || !icmp_nd_router_prefix_valid(cur)) { 01303 return; 01304 } 01305 01306 /* Base buffer size: RA Hdr = 12, ABRO = 24, MTU = up to 8, SLLAO = up to 16 */ 01307 uint16_t length = 12 + 24 + 8 + 16; 01308 length += 32 * ns_list_count(&cur->prefix_list); 01309 01310 ns_list_foreach(lowpan_context_t, context_ptr, &cur->context_list) { 01311 length += (context_ptr->length <= 64) ? 16 : 24; 01312 } 01313 01314 buffer_t *db = buffer_get(length); 01315 if (!db) { 01316 return; 01317 } else if (addr_interface_get_ll_address(cur_interface, db->src_sa .address , 0) != 0) { 01318 buffer_free(db); 01319 return; 01320 } 01321 db->src_sa .addr_type = ADDR_IPV6 ; 01322 01323 uint8_t *dptr = buffer_data_pointer(db); 01324 *dptr++ = cur_interface->adv_cur_hop_limit; 01325 *dptr++ = cur->flags; 01326 dptr = common_write_16_bit(cur->life_time, dptr); 01327 dptr = common_write_32_bit(cur_interface->adv_reachable_time, dptr); 01328 dptr = common_write_32_bit(cur_interface->adv_retrans_timer, dptr); 01329 01330 //SET ABRO 01331 *dptr++ = ICMPV6_OPT_AUTHORITATIVE_BORDER_RTR; 01332 *dptr++ = 3; //Len * 8 byte 01333 01334 dptr = common_write_16_bit((uint16_t)cur->abro_version_num, dptr); 01335 dptr = common_write_16_bit((uint16_t)(cur->abro_version_num >> 16), dptr); 01336 dptr = common_write_16_bit(0, dptr); 01337 memcpy(dptr, cur->border_router, 16); 01338 dptr += 16; 01339 //SET Prefixs 01340 dptr = icmpv6_write_prefix_option(&cur->prefix_list, dptr, 0, cur_interface); 01341 01342 ns_list_foreach(lowpan_context_t, context_ptr, &cur->context_list) { 01343 *dptr++ = ICMPV6_OPT_6LOWPAN_CONTEXT; 01344 *dptr++ = (context_ptr->length <= 64) ? 2 : 3; 01345 *dptr++ = context_ptr->length; 01346 *dptr++ = context_ptr->cid | (context_ptr->compression ? LOWPAN_CONTEXT_C : 0); 01347 dptr = common_write_16_bit(0, dptr); 01348 dptr = common_write_16_bit((context_ptr->lifetime + 599) / 600, dptr); 01349 length = (context_ptr->length <= 64) ? 8 : 16; 01350 memcpy(dptr, context_ptr->prefix, length); 01351 dptr += length; 01352 } 01353 01354 //MTU 01355 if (cur_interface->adv_link_mtu != 0) { 01356 dptr = icmpv6_write_mtu_option(cur_interface->adv_link_mtu, dptr); 01357 } 01358 01359 /* RFC 6775 mandates SLLAO in RA */ 01360 dptr = icmpv6_write_icmp_lla(cur_interface, dptr, ICMPV6_OPT_SRC_LL_ADDR, true, db->src_sa .address ); 01361 01362 if (address) { 01363 memcpy(db->dst_sa .address , address, 16); 01364 } else { 01365 memcpy(db->dst_sa .address , ADDR_LINK_LOCAL_ALL_NODES, 16); 01366 } 01367 buffer_data_end_set(db, dptr); 01368 01369 01370 db->dst_sa .addr_type = ADDR_IPV6 ; 01371 db->interface = cur_interface; 01372 db->info = (buffer_info_t)(B_FROM_ICMP | B_TO_ICMP | B_DIR_DOWN); 01373 db->options .type = ICMPV6_TYPE_INFO_RA; 01374 db->options .code = 0; 01375 db->options .hop_limit = 255; 01376 arm_net_protocol_packet_handler(db, cur_interface); 01377 01378 } 01379 01380 void nd_ra_build_by_abro(const uint8_t *abro, const uint8_t *dest, protocol_interface_info_entry_t *cur_interface) 01381 { 01382 ns_list_foreach(nd_router_t, cur, &nd_router_list) { 01383 if (addr_ipv6_equal(cur->border_router, abro)) { 01384 nd_ra_build(cur, dest, cur_interface); 01385 } 01386 } 01387 } 01388 01389 01390 void nd_trigger_ras_from_rs(const uint8_t *unicast_adr, protocol_interface_info_entry_t *cur_interface) 01391 { 01392 ns_list_foreach(nd_router_t, cur, &nd_router_list) { 01393 if (cur->nwk_id == cur_interface->nwk_id) { 01394 if (icmp_nd_router_prefix_valid(cur)) { 01395 //Allocate 01396 icmpv6_trigger_ra_from_rs(cur_interface, unicast_adr, cur->border_router); 01397 } 01398 } else { 01399 tr_error("BIND_CONFIRM FAIL!!"); 01400 } 01401 } 01402 } 01403 01404 void nd_ns_forward_timer_reset(uint8_t *root_adr) 01405 { 01406 ns_list_foreach(nd_router_t, cur, &nd_router_list) { 01407 if (memcmp(root_adr, cur->border_router, 16) == 0) { 01408 if (cur->ns_forward_timer) { 01409 cur->ns_forward_timer = 0; 01410 tr_warn("RX VALID DAC"); 01411 } 01412 break; 01413 } 01414 } 01415 } 01416 01417 static void nd_router_forward_timer(nd_router_t *cur, uint16_t ticks_update) 01418 { 01419 protocol_interface_info_entry_t *cur_interface; 01420 if (!(cur->ns_forward_timer)) { 01421 return; 01422 } 01423 01424 if (cur->ns_forward_timer > ticks_update) { 01425 cur->ns_forward_timer -= ticks_update; 01426 return; 01427 } 01428 01429 cur->ns_forward_timer = 0; 01430 cur_interface = protocol_stack_interface_info_get(cur->nwk_id); 01431 if (cur_interface) { 01432 if (cur->nd_re_validate > 10) { 01433 tr_debug("TRIG NS/ND"); 01434 cur->nd_timer = 1; 01435 cur->nd_re_validate = 1; 01436 } 01437 if (cur_interface->if_6lowpan_dad_process.active == false) { 01438 nd_ns_trig(cur, cur_interface); 01439 } 01440 } 01441 } 01442 01443 ipv6_ra_timing_t *nd_ra_timing(const uint8_t abro[16]) 01444 { 01445 ns_list_foreach(nd_router_t, cur, &nd_router_list) { 01446 if (addr_ipv6_equal(abro, cur->border_router)) { 01447 return &cur->ra_timing; 01448 } 01449 } 01450 01451 return NULL; 01452 } 01453 01454 static nd_router_t *nd_router_object_scan_by_prefix(const uint8_t *ptr, nwk_interface_id nwk_id) 01455 { 01456 ns_list_foreach(nd_router_t, cur, &nd_router_list) { 01457 if (cur->nwk_id == nwk_id) { 01458 if (icmpv6_prefix_compare(&cur->prefix_list, ptr, 64)) { 01459 return cur; 01460 } 01461 } 01462 } 01463 01464 return NULL; 01465 } 01466 01467 #endif 01468 01469 void gp_address_add_to_end(gp_ipv6_address_list_t *list, const uint8_t address[static 16]) 01470 { 01471 gp_ipv6_address_entry_t *new_entry; 01472 01473 ns_list_foreach(gp_ipv6_address_entry_t, cur, list) { 01474 if (memcmp(cur->address, address, 16) == 0) { 01475 return; 01476 } 01477 } 01478 01479 new_entry = ns_dyn_mem_alloc(sizeof(gp_ipv6_address_entry_t)); 01480 if (!new_entry) { 01481 tr_warn("No heap for New Address"); 01482 return; 01483 } 01484 01485 memcpy(new_entry->address, address, 16); 01486 ns_list_add_to_end(list, new_entry); 01487 } 01488 01489 /* Returns 1 if the router object has been removed */ 01490 static uint8_t nd_router_ready_timer(nd_router_t *cur, protocol_interface_info_entry_t *cur_interface, uint16_t ticks_update) 01491 { 01492 if (!cur->nd_timer) { 01493 return 0; 01494 } 01495 01496 if (cur->nd_timer > ticks_update ) { 01497 cur->nd_timer -= ticks_update; 01498 return 0; 01499 } 01500 01501 //Take out last remaing time from ticks 01502 ticks_update -= cur->nd_timer; 01503 uint16_t updated_seconds = 1; 01504 cur->nd_timer = 10; 01505 if (ticks_update) { 01506 updated_seconds += (ticks_update / 10); 01507 //Set Next second based on over based time 01508 cur->nd_timer -= (ticks_update % 10); 01509 } 01510 01511 if (icmp_nd_router_prefix_ttl_update(cur, cur_interface, updated_seconds)) { 01512 return 1; 01513 } 01514 01515 //Update seconds 01516 icmp_nd_router_context_ttl_update(cur, updated_seconds); 01517 01518 if (!cur->nd_re_validate) { 01519 return 0; 01520 } 01521 01522 if (cur->nd_re_validate > updated_seconds) { 01523 cur->nd_re_validate -= updated_seconds; 01524 //tr_debug("NDR:Tick Update %u", cur->nd_re_validate); 01525 return 0; 01526 } 01527 01528 if (cur->nd_state == ND_READY) { 01529 tr_debug("RE ND Process: RS Unicast!"); 01530 cur->ns_retry = nd_params.rs_retry_max; 01531 cur->nd_state = ND_RS_UNCAST; 01532 set_power_state(ICMP_ACTIVE); 01533 cur->nd_timer = 1; 01534 cur->nd_bootstrap_tick = (nd_base_tick -1); 01535 if (cur_interface->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE) { 01536 mac_data_poll_init_protocol_poll(cur_interface); 01537 } 01538 nd_router_bootstrap_timer(cur,cur_interface,1); 01539 } 01540 else { /* ND_BR_READY */ 01541 nd_border_router_setup_refresh(cur->nwk_id, true); 01542 tr_debug("ND BR refresh ABRO"); 01543 cur->nd_re_validate = (cur->life_time / 4) * 3; 01544 icmpv6_restart_router_advertisements(cur_interface, cur->border_router); 01545 } 01546 return 0; 01547 } 01548 01549 /* Returns 1 if the router object has been removed, or we want no further processing on this tick */ 01550 static uint8_t nd_router_bootstrap_timer(nd_router_t *cur, protocol_interface_info_entry_t *cur_interface, uint16_t ticks) 01551 { 01552 uint16_t scaled_ticks; 01553 /* 01554 * nd_timer is scaled by nd_base_tick during the discovery states, 01555 * to allow API to slow down the ND process. Note we count up and test 01556 * inequality, just in case someone decides to change nd_base_tick on 01557 * the fly. 01558 */ 01559 if (cur->nd_bootstrap_tick + ticks < nd_base_tick) { 01560 cur->nd_bootstrap_tick += ticks; 01561 return 0; 01562 } 01563 01564 //Take off scaled ticks 01565 ticks -= (nd_base_tick - cur->nd_bootstrap_tick); 01566 01567 scaled_ticks = 1 + (ticks / nd_base_tick); 01568 01569 cur->nd_bootstrap_tick = 0 + (ticks % nd_base_tick); 01570 01571 if (!cur->nd_timer) { 01572 tr_debug("NDB:Tick Update fail %u", scaled_ticks); 01573 return 0; 01574 } 01575 01576 01577 if (cur->nd_timer > scaled_ticks) { 01578 cur->nd_timer -= scaled_ticks; 01579 return 0; 01580 } 01581 01582 switch (cur->nd_state) { 01583 01584 case ND_RS_UNCAST: 01585 case ND_RS_MULTICAST: 01586 if (cur->ns_retry) { 01587 if (nd_rs_build(cur->nd_state == ND_RS_UNCAST ? cur : NULL, cur_interface)) { 01588 cur->nd_timer = nd_params.rs_retry_interval_min; 01589 cur->nd_timer += randLIB_get_16bit() & nd_params.timer_random_max; 01590 cur->ns_retry--; 01591 tr_debug(cur->nd_state == ND_RS_UNCAST ? "RS" : "RS+"); 01592 } else { 01593 cur->nd_timer = 2; 01594 } 01595 } else { 01596 //ND FAIL 01597 if (cur->nd_state == ND_RS_UNCAST) { 01598 cur->ns_retry = nd_params.rs_retry_max; 01599 cur->nd_state = ND_RS_MULTICAST; 01600 cur->nd_timer = 1; 01601 } else { 01602 //RS UNICAST Fail 01603 /*if (rpl_object_poisons() == 0) ??? */ { 01604 protocol_6lowpan_bootstrap_re_start(cur_interface); 01605 } 01606 return 1; 01607 } 01608 } 01609 break; 01610 01611 case ND_READY: 01612 case ND_BR_READY: 01613 /* Not called for these states - put in to suppress GCC warning */ 01614 break; 01615 } 01616 01617 return 0; 01618 } 01619 01620 01621 void nd_object_timer(protocol_interface_info_entry_t *cur_interface, uint16_t ticks_update) 01622 { 01623 ns_list_foreach_safe(nd_router_t, cur, &nd_router_list) { 01624 /* This may nd_router_remove(cur), so need to use safe loop */ 01625 if (cur_interface->nwk_id == cur->nwk_id) { 01626 01627 protocol_6lowpan_link_advertise_handle(cur, cur_interface, ticks_update); 01628 01629 if (cur->nd_state != ND_BR_READY) { 01630 nd_router_forward_timer(cur, ticks_update); 01631 } 01632 01633 if (nd_is_ready_state(cur->nd_state)) { 01634 nd_router_ready_timer(cur, cur_interface, ticks_update); 01635 } else { 01636 nd_router_bootstrap_timer(cur, cur_interface, ticks_update); 01637 } 01638 return; 01639 } 01640 } 01641 } 01642 01643 uint32_t nd_object_time_to_next_nd_reg(void) 01644 { 01645 uint32_t ret_val = 0; 01646 ns_list_foreach(nd_router_t, cur, &nd_router_list) { 01647 if (cur->nd_state == ND_READY) { 01648 ret_val = cur->nd_re_validate; 01649 ret_val++; 01650 ret_val *= 1000; 01651 /* XXX surely this should find the shortest, not the first? */ 01652 break; 01653 } 01654 } 01655 return ret_val; 01656 } 01657 01658 uint8_t nd_prefix_dst_check(uint8_t *ptr) 01659 { 01660 ns_list_foreach(nd_router_t, cur, &nd_router_list) { 01661 if (icmpv6_prefix_compare(&cur->prefix_list, ptr, 64)) { 01662 return 1; 01663 } 01664 } 01665 return 0; 01666 } 01667 01668 01669 int8_t nd_parent_loose_indcate(uint8_t *neighbor_address, protocol_interface_info_entry_t *cur_interface) 01670 { 01671 int8_t ret_val = -1; 01672 addrtype_t adr_type = ADDR_802_15_4_LONG ; 01673 uint8_t *adr_ptr = neighbor_address; 01674 nd_router_next_hop *hop; 01675 uint8_t compare_len = 8; 01676 01677 ns_list_foreach(nd_router_t, cur, &nd_router_list) { 01678 if (!(cur_interface->lowpan_info & INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY)) { 01679 continue; 01680 } 01681 01682 hop = &cur->default_hop; 01683 if (memcmp(neighbor_address, ADDR_SHORT_ADR_SUFFIC, 6) == 0) { 01684 adr_ptr += 6; 01685 adr_type = ADDR_802_15_4_SHORT ; 01686 compare_len = 2; 01687 } 01688 if (hop->addrtype == adr_type) { 01689 if (memcmp(hop->address, adr_ptr, compare_len) == 0) { 01690 tr_debug("ND Primary Parent Lost"); 01691 01692 if (cur->secondaty_hop == 0) { 01693 ret_val = -1; 01694 } else { 01695 ret_val = 0; 01696 tr_debug("Swap Secondary to primary"); 01697 memcpy(hop, cur->secondaty_hop, sizeof(nd_router_next_hop)); 01698 tr_debug("Trig NS/NA with new parent"); 01699 if (cur->nd_state == ND_READY) { 01700 cur->nd_re_validate = 1; 01701 if (cur_interface->if_6lowpan_dad_process.active == false) { 01702 nd_ns_trig(cur, cur_interface); 01703 } 01704 } 01705 ns_dyn_mem_free(cur->secondaty_hop); 01706 cur->secondaty_hop = 0; 01707 } 01708 return ret_val; 01709 } 01710 } else if (cur->secondaty_hop) { 01711 hop = cur->secondaty_hop; 01712 if (hop->addrtype == adr_type) { 01713 if (memcmp(hop->address, adr_ptr, compare_len) == 0) { 01714 tr_debug("ND Secondary Parent Lost"); 01715 ns_dyn_mem_free(cur->secondaty_hop); 01716 cur->secondaty_hop = 0; 01717 return 0; 01718 } 01719 } 01720 } 01721 } 01722 return -1; 01723 } 01724 01725 nd_router_t *nd_get_object_by_nwk_id(nwk_interface_id nwk_id) 01726 { 01727 ns_list_foreach(nd_router_t, cur, &nd_router_list) { 01728 if (cur->nwk_id == nwk_id) { 01729 return cur; 01730 } 01731 } 01732 01733 return 0; 01734 } 01735 01736 nd_router_t *nd_get_pana_address(void) 01737 { 01738 return ns_list_get_first(&nd_router_list); 01739 } 01740 01741 void nd_6lowpan_set_radv_params(protocol_interface_info_entry_t *cur_interface) 01742 { 01743 #ifndef NO_RADV_TX 01744 cur_interface->max_ra_delay_time = 20; 01745 cur_interface->min_delay_between_ras = 100; 01746 cur_interface->rtr_adv_unicast_to_rs = true; 01747 cur_interface->adv_cur_hop_limit = nd_params.ra_cur_hop_limit; 01748 cur_interface->adv_link_mtu = nd_params.ra_link_mtu; 01749 cur_interface->adv_reachable_time = nd_params.ra_reachable_time; 01750 cur_interface->adv_retrans_timer = nd_params.ra_retrans_timer; 01751 cur_interface->max_initial_rtr_adv_interval = nd_params.ra_interval_min; 01752 cur_interface->max_initial_rtr_advertisements = nd_params.ra_transmits; 01753 #endif 01754 } 01755 #endif // HAVE_6LOWPAN_ND 01756
Generated on Tue Aug 9 2022 00:37:16 by
1.7.2