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