Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
ns_address_internal.c
00001 /* 00002 * Copyright (c) 2008, 2010-2019, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 /** 00018 * \file ns_address_internal.c 00019 * \brief Utility functions concerning addresses 00020 * 00021 * This file contains all the utility functions that can be used to 00022 * check, manipulate etc. addresses. 00023 */ 00024 #include "nsconfig.h" 00025 #include "ns_types.h" 00026 #include "ip6string.h" 00027 #include "ns_trace.h" 00028 #include "randLIB.h" 00029 #include "string.h" 00030 #include "nsdynmemLIB.h" 00031 #include "ns_sha256.h" 00032 #include "socket_api.h" 00033 #include "Common_Protocols/ipv6_constants.h" 00034 #include "Common_Protocols/icmpv6.h" 00035 #include "Common_Protocols/mld.h" 00036 #include "6LoWPAN/Thread/thread_common.h" 00037 #include "common_functions.h" 00038 00039 #include "RPL/rpl_control.h" 00040 00041 #define TRACE_GROUP "addr" 00042 00043 typedef struct addr_notification { 00044 if_address_notification_fn *fn; 00045 ns_list_link_t link; 00046 } addr_notification_t; 00047 00048 static NS_LIST_DEFINE(addr_notifications, addr_notification_t, link); 00049 00050 typedef struct addr_policy_table_entry_t { 00051 uint8_t prefix[16]; 00052 uint8_t prefix_len; 00053 uint8_t precedence; 00054 uint8_t label; 00055 ns_list_link_t link; 00056 } addr_policy_table_entry_t; 00057 00058 static NS_LIST_DEFINE(addr_policy_table, addr_policy_table_entry_t, link); 00059 00060 uint32_t addr_preferences_default = SOCKET_IPV6_PREFER_SRC_TMP | SOCKET_IPV6_PREFER_SRC_6LOWPAN_SHORT; 00061 00062 static void addr_policy_table_reset(void); 00063 static void addr_max_entries_check(protocol_interface_info_entry_t *cur, if_address_source_t source); 00064 00065 const uint8_t ADDR_LINK_LOCAL_PREFIX[8] = { 0xfe, 0x80 }; 00066 const uint8_t ADDR_SHORT_ADR_SUFFIC[6] = { 0x00, 0x00, 0x00, 0xff, 0xfe, 0x00}; 00067 00068 const uint8_t ADDR_MULTICAST_SOLICITED[13] = { 0xff, 0x02, [11] = 0x01, 0xff}; 00069 const uint8_t ADDR_IF_LOCAL_ALL_NODES[16] = { 0xff, 0x01, [15] = 0x01 }; 00070 const uint8_t ADDR_IF_LOCAL_ALL_ROUTERS[16] = { 0xff, 0x01, [15] = 0x02 }; 00071 const uint8_t ADDR_LINK_LOCAL_ALL_NODES[16] = { 0xff, 0x02, [15] = 0x01 }; 00072 const uint8_t ADDR_LINK_LOCAL_ALL_ROUTERS[16] = { 0xff, 0x02, [15] = 0x02 }; 00073 const uint8_t ADDR_LINK_LOCAL_ALL_MLDV2_ROUTERS[16] = { 0xff, 0x02, [15] = 0x16 }; 00074 const uint8_t ADDR_LINK_LOCAL_MDNS[16] = { 0xff, 0x02, [15] = 0xfb }; 00075 const uint8_t ADDR_REALM_LOCAL_ALL_NODES[16] = { 0xff, 0x03, [15] = 0x01 }; 00076 const uint8_t ADDR_REALM_LOCAL_ALL_ROUTERS[16] = { 0xff, 0x03, [15] = 0x02 }; 00077 const uint8_t ADDR_SITE_LOCAL_ALL_ROUTERS[16] = { 0xff, 0x05, [15] = 0x02 }; 00078 const uint8_t ADDR_ALL_MPL_FORWARDERS[16] = { 0xff, 0x03, [15] = 0xfc }; 00079 const uint8_t ADDR_ALL_DHCP_RELAY_AGENTS_AND_SERVERS[16] = { 0xff, 0x02, [13] = 0x01, 0x00, 0x02 }; 00080 00081 const uint8_t ADDR_IPV4_MAPPED_PREFIX[12] = { [10] = 0xff, 0xff }; 00082 const uint8_t ADDR_LOOPBACK[16] = { [15] = 1 }; 00083 const uint8_t ADDR_UNSPECIFIED[16] = { 0 }; /* Note a few bits of code check for pointer equality with ADDR_UNSPECIFIED */ 00084 #define ADDR_IPV4_COMPATIBLE ADDR_LOOPBACK /* First 96 bits match...*/ 00085 00086 #define ADDR_MULTICAST_LINK_PREFIX ADDR_LINK_LOCAL_ALL_NODES /* ff02::xx */ 00087 #define ADDR_MULTICAST_REALM_PREFIX ADDR_ALL_MPL_FORWARDERS /* ff03::xx */ 00088 00089 static const uint8_t *addr_iid_secret_key; 00090 static const uint8_t *addr_initial_iid; 00091 static uint8_t addr_iid_secret_key_len; 00092 00093 static bool addr_am_implicit_group_member(const uint8_t group[static 16]) 00094 { 00095 static const uint8_t *const implicit_groups[] = { 00096 ADDR_LINK_LOCAL_ALL_NODES, 00097 ADDR_IF_LOCAL_ALL_NODES, 00098 }; 00099 00100 for (uint_fast8_t i = 0; i < sizeof implicit_groups / sizeof implicit_groups[0]; i++) { 00101 if (addr_ipv6_equal(implicit_groups[i], group)) { 00102 return true; 00103 } 00104 } 00105 return false; 00106 } 00107 00108 uint8_t addr_len_from_type(addrtype_t addr_type) 00109 { 00110 switch (addr_type) { 00111 case ADDR_NONE : 00112 return 0; 00113 case ADDR_802_15_4_SHORT : 00114 return 2 + 2; /* Some users don't have the PAN ID */ 00115 case ADDR_802_15_4_LONG : 00116 return 2 + 8; 00117 case ADDR_EUI_48 : 00118 return 6; 00119 case ADDR_IPV6 : 00120 return 16; 00121 case ADDR_BROADCAST : 00122 return 0; /* Don't really handle this */ 00123 } 00124 return 0; 00125 } 00126 00127 /** 00128 * Check if an address is a broadcast address 00129 * 00130 * \param addr pointer to an address_t containing the address to be checked 00131 * \param addr_type the type of the address_t 00132 * \return 0 if the address is a broadcast address 00133 */ 00134 uint8_t addr_check_broadcast(const address_t addr, addrtype_t addr_type) 00135 { 00136 switch (addr_type) { 00137 case ADDR_802_15_4_SHORT : 00138 break; 00139 case ADDR_BROADCAST : 00140 return 0; 00141 default: 00142 return 1; 00143 } 00144 00145 uint8_t size = 2; 00146 uint8_t *ptr = (uint8_t *) addr; 00147 ptr += 2; 00148 00149 while (size) { 00150 if ((*ptr++) != 0xFF) { 00151 break; 00152 } else { 00153 size--; 00154 } 00155 } 00156 return (size); 00157 00158 } 00159 00160 bool addr_is_ipv6_link_local(const uint8_t addr[static 16]) 00161 { 00162 return addr[0] == 0xfe && (addr[1] & 0xc0) == 0x80; 00163 } 00164 00165 /* Site-local addresses deprecated, but still processed by RFC 6724 address selection */ 00166 static bool addr_is_ipv6_site_local(const uint8_t addr[static 16]) 00167 { 00168 return addr[0] == 0xfe && (addr[1] & 0xc0) == 0xc0; 00169 } 00170 00171 static bool addr_is_ipv4_mapped(const uint8_t addr[static 16]) 00172 { 00173 return memcmp(addr, ADDR_IPV4_MAPPED_PREFIX, 12) == 0; 00174 } 00175 00176 /* Scope(A), as defined in RFC 6724 plus RFC 4007 */ 00177 uint_fast8_t addr_ipv6_scope(const uint8_t addr[static 16], const protocol_interface_info_entry_t *interface) 00178 { 00179 #ifndef HAVE_THREAD 00180 (void)interface; 00181 #endif 00182 if (addr_is_ipv6_multicast(addr)) { 00183 return addr_ipv6_multicast_scope(addr); 00184 } 00185 if (addr_is_ipv6_link_local(addr) || addr_is_ipv6_loopback(addr)) { 00186 return IPV6_SCOPE_LINK_LOCAL; 00187 } 00188 if (addr_is_ipv6_site_local(addr)) { 00189 return IPV6_SCOPE_SITE_LOCAL; 00190 } 00191 /* Thread-specific hack - we want to treat one specific "mesh local" ULA as 00192 * "realm local" scope. (This is necessary, for example, to use a 00193 * mesh-local ULA address as source when sending realm-local multicast). 00194 */ 00195 if (thread_addr_is_mesh_local(addr, interface)) { 00196 return IPV6_SCOPE_REALM_LOCAL; 00197 } 00198 if (addr_is_ipv4_mapped(addr)) { 00199 if ((addr[12] == 169 && addr[13] == 254) || addr[12] == 127) { 00200 return IPV6_SCOPE_LINK_LOCAL; 00201 } 00202 return IPV6_SCOPE_GLOBAL; 00203 } 00204 return IPV6_SCOPE_GLOBAL; 00205 } 00206 00207 void address_module_init(void) 00208 { 00209 addr_policy_table_reset(); 00210 //mac_reset_short_address(); 00211 } 00212 00213 #ifdef MULTICAST_FORWARDING 00214 static if_group_fwd_entry_t *addr_multicast_fwd_list_lookup(if_group_fwd_list_t *list, const uint8_t group[16]) 00215 { 00216 ns_list_foreach(if_group_fwd_entry_t, e, list) { 00217 if (addr_ipv6_equal(e->group, group)) { 00218 return e; 00219 } 00220 } 00221 return NULL; 00222 } 00223 00224 bool addr_multicast_fwd_check(protocol_interface_info_entry_t *interface, const uint8_t group[16]) 00225 { 00226 return addr_multicast_fwd_list_lookup(&interface->ip_groups_fwd, group) != NULL; 00227 } 00228 00229 static void addr_multicast_fwd_adjust_upstream(protocol_interface_info_entry_t *downstream, protocol_interface_info_entry_t *upstream, const uint8_t group[16], bool add) 00230 { 00231 if (!upstream || downstream == upstream || !downstream->ip_multicast_forwarding) { 00232 return; 00233 } 00234 uint8_t group_scope = addr_ipv6_multicast_scope(group); 00235 if (downstream->zone_index[group_scope] == upstream->zone_index[group_scope]) { 00236 tr_debug("Multicast proxy %s %s", add ? "add" : "remove", trace_ipv6(group)); 00237 if (add) { 00238 addr_add_group(upstream, group); 00239 } else { 00240 addr_remove_group(upstream, group); 00241 } 00242 } 00243 } 00244 00245 void addr_multicast_fwd_adjust_upstream_full(protocol_interface_info_entry_t *upstream, bool add) 00246 { 00247 ns_list_foreach(protocol_interface_info_entry_t, interface, &protocol_interface_info_list) { 00248 ns_list_foreach(if_group_fwd_entry_t, group, &interface->ip_groups_fwd) { 00249 addr_multicast_fwd_adjust_upstream(interface, upstream, group->group, add); 00250 } 00251 } 00252 } 00253 00254 void addr_multicast_fwd_set_forwarding(struct protocol_interface_info_entry *interface, bool enable) 00255 { 00256 /* Do nothing if enable state isn't changing */ 00257 if (interface->ip_multicast_forwarding == enable) { 00258 return; 00259 } 00260 00261 /* If we disable forwarding on upstream, clear it out to avoid maintenance confusion */ 00262 if (!enable && interface == protocol_core_multicast_upstream) { 00263 multicast_fwd_set_proxy_upstream(-1); 00264 } 00265 00266 /* Adjust routine checks that forwarding is on before doing any processing. So make sure it's on 00267 * now, then we'll set requested state afterwards. */ 00268 interface->ip_multicast_forwarding = true; 00269 00270 /* Add or remove all groups on changing downstream interface to upstream */ 00271 if (protocol_core_multicast_upstream) { 00272 ns_list_foreach(if_group_fwd_entry_t, group, &interface->ip_groups_fwd) { 00273 addr_multicast_fwd_adjust_upstream(interface, protocol_core_multicast_upstream, group->group, enable); 00274 } 00275 } 00276 00277 interface->ip_multicast_forwarding = enable; 00278 } 00279 00280 bool addr_multicast_fwd_add(protocol_interface_info_entry_t *interface, const uint8_t group[16], uint32_t lifetime) 00281 { 00282 if_group_fwd_entry_t *entry = addr_multicast_fwd_list_lookup(&interface->ip_groups_fwd, group); 00283 if (entry) { 00284 if (entry->lifetime < lifetime) { 00285 entry->lifetime = lifetime; 00286 } 00287 return true; 00288 } 00289 entry = ns_dyn_mem_alloc(sizeof * entry); 00290 if (!entry) { 00291 return false; 00292 } 00293 memcpy(entry->group, group, 16); 00294 ns_list_add_to_end(&interface->ip_groups_fwd, entry); 00295 addr_multicast_fwd_adjust_upstream(interface, protocol_core_multicast_upstream, group, true); 00296 entry->lifetime = lifetime; 00297 tr_debug("MC fwd added to IF %d: %s", interface->id, trace_ipv6(group)); 00298 return true; 00299 } 00300 00301 static void addr_multicast_fwd_delete_entry(protocol_interface_info_entry_t *interface, if_group_fwd_entry_t *entry) 00302 { 00303 addr_multicast_fwd_adjust_upstream(interface, protocol_core_multicast_upstream, entry->group, false); 00304 ns_list_remove(&interface->ip_groups_fwd, entry); 00305 ns_dyn_mem_free(entry); 00306 } 00307 00308 bool addr_multicast_fwd_remove(protocol_interface_info_entry_t *interface, const uint8_t group[16]) 00309 { 00310 if_group_fwd_entry_t *entry = addr_multicast_fwd_list_lookup(&interface->ip_groups_fwd, group); 00311 if (!entry) { 00312 return false; 00313 } 00314 00315 tr_debug("MC fwd removed from IF %d: %s", interface->id, trace_ipv6(group)); 00316 addr_multicast_fwd_delete_entry(interface, entry); 00317 00318 return true; 00319 } 00320 #endif // MULTICAST_FORWARDING 00321 00322 int_fast8_t addr_policy_table_add_entry(const uint8_t *prefix, uint8_t len, uint8_t precedence, uint8_t label) 00323 { 00324 addr_policy_table_entry_t *entry = ns_dyn_mem_alloc(sizeof(addr_policy_table_entry_t)); 00325 if (!entry) { 00326 return -1; 00327 } 00328 bitcopy(entry->prefix, prefix, len); 00329 entry->prefix_len = len; 00330 entry->precedence = precedence; 00331 entry->label = label; 00332 00333 /* Table is sorted longest-prefix-first, for longest-match searching */ 00334 bool inserted = false; 00335 ns_list_foreach(addr_policy_table_entry_t, before, &addr_policy_table) { 00336 if (before->prefix_len > len) { 00337 continue; 00338 } 00339 if (before->prefix_len == len && bitsequal(before->prefix, prefix, len)) { 00340 ns_dyn_mem_free(entry); 00341 return -2; 00342 } 00343 ns_list_add_before(&addr_policy_table, before, entry); 00344 inserted = true; 00345 break; 00346 } 00347 00348 if (!inserted) { 00349 ns_list_add_to_end(&addr_policy_table, entry); 00350 } 00351 00352 return 0; 00353 } 00354 00355 int_fast8_t addr_policy_table_delete_entry(const uint8_t *prefix, uint8_t len) 00356 { 00357 ns_list_foreach(addr_policy_table_entry_t, entry, &addr_policy_table) { 00358 if (entry->prefix_len == len && bitsequal(entry->prefix, prefix, len)) { 00359 ns_list_remove(&addr_policy_table, entry); 00360 ns_dyn_mem_free(entry); 00361 return 0; 00362 } 00363 } 00364 00365 return -1; 00366 } 00367 /// @TODO do we need this test print anymore ? 00368 void addr_policy_table_print(void) 00369 { 00370 ns_list_foreach(addr_policy_table_entry_t, entry, &addr_policy_table) { 00371 char addr[40]; 00372 ip6tos(entry->prefix, addr); 00373 tr_debug("%3d %3d %s/%u\n", entry->precedence, entry->label, addr, entry->prefix_len); 00374 } 00375 } 00376 00377 static void addr_policy_table_reset(void) 00378 { 00379 ns_list_foreach_safe(addr_policy_table_entry_t, entry, &addr_policy_table) { 00380 ns_list_remove(&addr_policy_table, entry); 00381 ns_dyn_mem_free(entry); 00382 } 00383 00384 /* Default policy table from RFC 6724 */ 00385 addr_policy_table_add_entry(ADDR_LOOPBACK, 128, 50, 0); 00386 addr_policy_table_add_entry(NULL, 0, 40, 1); 00387 addr_policy_table_add_entry(ADDR_IPV4_MAPPED_PREFIX, 96, 35, 4); 00388 addr_policy_table_add_entry((const uint8_t[]) { 00389 0x20, 0x02 00390 }, 16, 30, 2); 00391 addr_policy_table_add_entry((const uint8_t[]) { 00392 0x20, 0x01, 0, 0 00393 }, 32, 5, 5); 00394 addr_policy_table_add_entry((const uint8_t[]) { 00395 0xfc 00396 }, 7, 3, 13); 00397 addr_policy_table_add_entry(ADDR_IPV4_COMPATIBLE, 96, 1, 3); 00398 addr_policy_table_add_entry((const uint8_t[]) { 00399 0xfe, 0xc0 00400 }, 10, 1, 11); 00401 addr_policy_table_add_entry((const uint8_t[]) { 00402 0x3f, 0xfe 00403 }, 16, 1, 12); 00404 //addr_policy_table_print(); 00405 } 00406 00407 static const addr_policy_table_entry_t *addr_get_policy(const uint8_t addr[static 16]) 00408 { 00409 ns_list_foreach(const addr_policy_table_entry_t, entry, &addr_policy_table) { 00410 if (bitsequal(entry->prefix, addr, entry->prefix_len)) { 00411 return entry; 00412 } 00413 } 00414 00415 /* Shouldn't happen - should always have a default entry */ 00416 return NULL; 00417 } 00418 00419 /* RFC 6724 CommonPrefixLen(S, D) */ 00420 static uint_fast8_t addr_common_prefix_len(const uint8_t src[static 16], uint_fast8_t src_prefix_len, const uint8_t dst[static 16]) 00421 { 00422 uint_fast8_t common = 0; 00423 00424 while (src_prefix_len >= 8 && *src == *dst) { 00425 common += 8; 00426 src_prefix_len -= 8; 00427 ++src; 00428 ++dst; 00429 } 00430 00431 if (src_prefix_len) { 00432 uint8_t trail = common_count_leading_zeros_8(*src ^ *dst); 00433 if (trail > src_prefix_len) { 00434 trail = src_prefix_len; 00435 } 00436 common += trail; 00437 } 00438 00439 return common; 00440 } 00441 00442 if_address_entry_t *addr_get_entry(const protocol_interface_info_entry_t *interface, const uint8_t addr[static 16]) 00443 { 00444 ns_list_foreach(if_address_entry_t, entry, &interface->ip_addresses) { 00445 if (addr_ipv6_equal(entry->address, addr)) { 00446 return entry; 00447 } 00448 } 00449 00450 return NULL; 00451 } 00452 00453 bool addr_is_assigned_to_interface(const protocol_interface_info_entry_t *interface, const uint8_t addr[static 16]) 00454 { 00455 if_address_entry_t *entry = addr_get_entry(interface, addr); 00456 return entry && !entry->tentative; 00457 } 00458 00459 bool addr_is_tentative_for_interface(const protocol_interface_info_entry_t *interface, const uint8_t addr[static 16]) 00460 { 00461 if_address_entry_t *entry = addr_get_entry(interface, addr); 00462 return entry && entry->tentative; 00463 } 00464 00465 if_group_entry_t *addr_add_group(protocol_interface_info_entry_t *interface, const uint8_t group[static 16]) 00466 { 00467 if_group_entry_t *entry = addr_get_group_entry(interface, group); 00468 if (entry) { 00469 if (entry->ref_count != 0xFFFF) { 00470 entry->ref_count++; 00471 } 00472 return entry; 00473 } 00474 00475 if (!addr_is_ipv6_multicast(group)) { 00476 return NULL; 00477 } 00478 00479 if (addr_am_implicit_group_member(group)) { 00480 return NULL; 00481 } 00482 00483 entry = ns_dyn_mem_alloc(sizeof(if_group_entry_t)); 00484 if (!entry) { 00485 return NULL; 00486 } 00487 memcpy(entry->group, group, 16); 00488 entry->ref_count = 1; 00489 ns_list_add_to_end(&interface->ip_groups, entry); 00490 00491 mld_start_listening(interface, entry); 00492 00493 return entry; 00494 } 00495 00496 /* This does reference count */ 00497 void addr_remove_group(protocol_interface_info_entry_t *interface, const uint8_t group[static 16]) 00498 { 00499 if_group_entry_t *entry = addr_get_group_entry(interface, group); 00500 if (entry) { 00501 if (entry->ref_count != 0xFFFF) { 00502 if (--entry->ref_count == 0) { 00503 addr_delete_group_entry(interface, entry); 00504 } 00505 } 00506 } 00507 } 00508 00509 /* This does NOT reference count - it actually deletes the entry */ 00510 void addr_delete_group_entry(protocol_interface_info_entry_t *interface, if_group_entry_t *entry) 00511 { 00512 mld_stop_listening(interface, entry); 00513 ns_list_remove(&interface->ip_groups, entry); 00514 ns_dyn_mem_free(entry); 00515 } 00516 00517 void addr_delete_group(protocol_interface_info_entry_t *interface, const uint8_t group[static 16]) 00518 { 00519 if_group_entry_t *entry = addr_get_group_entry(interface, group); 00520 if (entry) { 00521 addr_delete_group_entry(interface, entry); 00522 } 00523 } 00524 00525 if_group_entry_t *addr_get_group_entry(const protocol_interface_info_entry_t *interface, const uint8_t group[static 16]) 00526 { 00527 ns_list_foreach(if_group_entry_t, entry, &interface->ip_groups) { 00528 if (addr_ipv6_equal(entry->group, group)) { 00529 return entry; 00530 } 00531 } 00532 00533 return NULL; 00534 } 00535 00536 static void addr_generate_solicited_node_group(uint8_t group[static 16], const uint8_t addr[static 16]) 00537 { 00538 memcpy(group, ADDR_MULTICAST_SOLICITED, 13); 00539 memcpy(group + 13, addr + 13, 3); 00540 } 00541 00542 static if_group_entry_t *addr_add_solicited_node_group(protocol_interface_info_entry_t *interface, const uint8_t address[static 16]) 00543 { 00544 uint8_t group[16]; 00545 addr_generate_solicited_node_group(group, address); 00546 return addr_add_group(interface, group); 00547 } 00548 00549 static void addr_remove_solicited_node_group(protocol_interface_info_entry_t *interface, const uint8_t address[static 16]) 00550 { 00551 uint8_t group[16]; 00552 addr_generate_solicited_node_group(group, address); 00553 addr_remove_group(interface, group); 00554 } 00555 00556 void addr_add_router_groups(protocol_interface_info_entry_t *interface) 00557 { 00558 /* The standard IPv6 ones, but not "Realm-Local-All-Routers" 00559 * which is ZigBee IP / Thread-specific (and not IANA registered) 00560 */ 00561 addr_add_group(interface, ADDR_IF_LOCAL_ALL_ROUTERS); 00562 addr_add_group(interface, ADDR_LINK_LOCAL_ALL_ROUTERS); 00563 00564 /* We only want to join the site address on one interface per site zone, 00565 * or we'd get multiple copies of packets. Exit if we're already a member. 00566 */ 00567 ns_list_foreach(protocol_interface_info_entry_t, i, &protocol_interface_info_list) { 00568 if (i->zone_index[IPV6_SCOPE_SITE_LOCAL] == interface->zone_index[IPV6_SCOPE_SITE_LOCAL] && 00569 addr_get_group_entry(i, ADDR_SITE_LOCAL_ALL_ROUTERS)) { 00570 return; 00571 } 00572 } 00573 addr_add_group(interface, ADDR_SITE_LOCAL_ALL_ROUTERS); 00574 } 00575 00576 bool addr_am_group_member_on_interface(const protocol_interface_info_entry_t *interface, const uint8_t group[static 16]) 00577 { 00578 return addr_am_implicit_group_member(group) || addr_get_group_entry(interface, group); 00579 } 00580 00581 /* RFC 6724 Default source address selection */ 00582 const uint8_t *addr_select_source(protocol_interface_info_entry_t *interface, const uint8_t dest[static 16], uint32_t addr_preferences) 00583 { 00584 /* Let's call existing preferred address "SA" and new candidate "SB", to 00585 * make it look like a bit like RFC 6724 00586 */ 00587 if_address_entry_t *SA = NULL; 00588 uint_fast8_t scope_D = addr_ipv6_scope(dest, interface); 00589 const addr_policy_table_entry_t *policy_D = addr_get_policy(dest); 00590 00591 if (addr_preferences == 0) { 00592 addr_preferences = addr_preferences_default; 00593 } 00594 00595 /* 00596 * As we go around the loop, if we prefer the new "SB", we set SA to SB 00597 * and continue. If we decide we prefer the existing SA, we just continue. 00598 * 00599 * Careful with these macros - they must only be used with if/else, and 00600 * inside { }, as per the coding style rules. 00601 */ 00602 #define PREFER_SA continue 00603 #define PREFER_SB SA = SB; continue 00604 00605 ns_list_foreach(if_address_entry_t, SB, &interface->ip_addresses) { 00606 /* Ignore tentative addresses */ 00607 if (SB->tentative) { 00608 continue; 00609 } 00610 00611 /* First (non-tentative) address seen becomes SA */ 00612 if (!SA) { 00613 PREFER_SB; 00614 } 00615 00616 /* Rule 1: Prefer same address */ 00617 if (memcmp(SB->address, dest, 16) == 0) { 00618 SA = SB; 00619 /* It's an exact match, no point checking any other addresses */ 00620 break; 00621 } 00622 00623 /* Rule 2: Prefer appropriate scope */ 00624 uint_fast8_t scope_SA = addr_ipv6_scope(SA->address, interface); 00625 uint_fast8_t scope_SB = addr_ipv6_scope(SB->address, interface); 00626 if (scope_SA < scope_SB) { 00627 if (scope_SA < scope_D) { 00628 PREFER_SB; 00629 } else { 00630 PREFER_SA; 00631 } 00632 } else if (scope_SB < scope_SA) { 00633 if (scope_SB < scope_D) { 00634 PREFER_SA; 00635 } else { 00636 PREFER_SB; 00637 } 00638 } 00639 00640 /* Rule 3: Avoid deprecated addresses */ 00641 if (SA->preferred_lifetime != 0 && SB->preferred_lifetime == 0) { 00642 PREFER_SA; 00643 } else if (SB->preferred_lifetime != 0 && SA->preferred_lifetime == 0) { 00644 PREFER_SB; 00645 } 00646 00647 /* (Rule 4: Prefer home addresses - Mobile IPv6 not implemented) */ 00648 /* (Rule 5: Prefer outgoing interface - candidate set already limited) */ 00649 /* (Rule 5.5: Prefer addresses in a prefix advertised by the next-hop - we don't track this information) */ 00650 00651 /* Rule 6: Prefer matching label */ 00652 const addr_policy_table_entry_t *policy_SA = addr_get_policy(SA->address); 00653 const addr_policy_table_entry_t *policy_SB = addr_get_policy(SB->address); 00654 if (policy_SA->label == policy_D->label && policy_SB->label != policy_D->label) { 00655 PREFER_SA; 00656 } else if (policy_SB->label == policy_D->label && policy_SA->label != policy_D->label) { 00657 PREFER_SB; 00658 } 00659 00660 /* Rule 7: Prefer temporary addresses (or the opposite) */ 00661 if (SA->temporary != SB->temporary) { 00662 bool prefer_public = (addr_preferences & SOCKET_IPV6_PREFER_SRC_PUBLIC); 00663 00664 if (SA->temporary != prefer_public) { 00665 PREFER_SA; 00666 } else { 00667 PREFER_SB; 00668 } 00669 } 00670 00671 /* Rule 8: Use longest matching prefix */ 00672 uint_fast8_t common_SA = addr_common_prefix_len(SA->address, SA->prefix_len, dest); 00673 uint_fast8_t common_SB = addr_common_prefix_len(SB->address, SB->prefix_len, dest); 00674 if (common_SA > common_SB) { 00675 PREFER_SA; 00676 } else if (common_SB > common_SA) { 00677 PREFER_SB; 00678 } 00679 00680 /* A tie-breaker: Prefer 6LoWPAN short address (or the opposite) */ 00681 bool short_SA = SA->prefix_len == 64 && memcmp(SA->address + 8, ADDR_SHORT_ADR_SUFFIC, 6) == 0; 00682 bool short_SB = SB->prefix_len == 64 && memcmp(SB->address + 8, ADDR_SHORT_ADR_SUFFIC, 6) == 0; 00683 if (short_SA != short_SB) { 00684 bool prefer_short = (addr_preferences & SOCKET_IPV6_PREFER_SRC_6LOWPAN_SHORT); 00685 00686 if (short_SA == prefer_short) { 00687 PREFER_SA; 00688 } else { 00689 PREFER_SB; 00690 } 00691 } 00692 00693 /* Rule 9 select most precated one */ 00694 if (policy_SA->precedence > policy_SB->precedence) { 00695 PREFER_SA; 00696 } else if (policy_SB->precedence > policy_SA->precedence) { 00697 PREFER_SB; 00698 } 00699 00700 /* Tie */ 00701 PREFER_SA; 00702 } 00703 00704 return SA ? SA->address : NULL; 00705 } 00706 00707 /* A variant of RFC 6724 Default source address selection, to select an address 00708 * on an interface with a specific prefix. The prefix must match, and some 00709 * source address rules don't apply, but some are handled similarly. See 00710 * comments in addr_select_source. 00711 */ 00712 const uint8_t *addr_select_with_prefix(protocol_interface_info_entry_t *cur, const uint8_t *prefix, uint8_t prefix_len, uint32_t addr_preferences) 00713 { 00714 if_address_entry_t *SA = NULL; 00715 00716 if (addr_preferences == 0) { 00717 addr_preferences = addr_preferences_default; 00718 } 00719 00720 ns_list_foreach(if_address_entry_t, SB, &cur->ip_addresses) { 00721 /* Ignore tentative addresses */ 00722 if (SB->tentative) { 00723 continue; 00724 } 00725 00726 /* Prefix must match */ 00727 if (!bitsequal(SB->address, prefix, prefix_len)) { 00728 continue; 00729 } 00730 00731 /* First (non-tentative, matching prefix) address seen becomes SA */ 00732 if (!SA) { 00733 PREFER_SB; 00734 } 00735 00736 /* (Rule 1: Prefer same address - doesn't apply here) */ 00737 /* Rule 2: Was prefer appropriate scope - for this purpose we instead prefer wider scope */ 00738 uint_fast8_t scope_SA = addr_ipv6_scope(SA->address, cur); 00739 uint_fast8_t scope_SB = addr_ipv6_scope(SB->address, cur); 00740 if (scope_SA < scope_SB) { 00741 PREFER_SB; 00742 } else if (scope_SB < scope_SA) { 00743 PREFER_SA; 00744 } 00745 00746 /* Rule 3: Avoid deprecated addresses */ 00747 if (SA->preferred_lifetime != 0 && SB->preferred_lifetime == 0) { 00748 PREFER_SA; 00749 } else if (SB->preferred_lifetime != 0 && SA->preferred_lifetime == 0) { 00750 PREFER_SB; 00751 } 00752 00753 /* (Rule 4: Prefer home addresses - Mobile IPv6 not implemented) */ 00754 /* (Rule 5: Prefer outgoing interface - candidate set already limited) */ 00755 /* (Rule 5.5: Prefer addresses in a prefix advertised by the next-hop - we don't track this information) */ 00756 00757 /* Rule 6: Prefer matching label - doesn't apply here. But instead, 00758 * let's use precedence, like rule 6 of destination selection. 00759 */ 00760 const addr_policy_table_entry_t *policy_SA = addr_get_policy(SA->address); 00761 const addr_policy_table_entry_t *policy_SB = addr_get_policy(SB->address); 00762 if (policy_SA->precedence > policy_SB->precedence) { 00763 PREFER_SA; 00764 } else if (policy_SB->precedence > policy_SA->precedence) { 00765 PREFER_SB; 00766 } 00767 00768 /* Rule 7: Prefer temporary addresses (or the opposite) */ 00769 if (SA->temporary != SB->temporary) { 00770 bool prefer_public = (addr_preferences & SOCKET_IPV6_PREFER_SRC_PUBLIC); 00771 00772 if (SA->temporary != prefer_public) { 00773 PREFER_SA; 00774 } else { 00775 PREFER_SB; 00776 } 00777 } 00778 00779 /* (Rule 8: Use longest matching prefix - doesn't apply) */ 00780 00781 /* A tie-breaker: Prefer 6LoWPAN short address (or the opposite) */ 00782 bool short_SA = SA->prefix_len == 64 && memcmp(SA->address + 8, ADDR_SHORT_ADR_SUFFIC, 6) == 0; 00783 bool short_SB = SB->prefix_len == 64 && memcmp(SB->address + 8, ADDR_SHORT_ADR_SUFFIC, 6) == 0; 00784 if (short_SA != short_SB) { 00785 bool prefer_short = (addr_preferences & SOCKET_IPV6_PREFER_SRC_6LOWPAN_SHORT); 00786 00787 if (short_SA == prefer_short) { 00788 PREFER_SA; 00789 } else { 00790 PREFER_SB; 00791 } 00792 } 00793 00794 /* Tie */ 00795 PREFER_SA; 00796 } 00797 00798 return SA ? SA->address : NULL; 00799 } 00800 00801 #undef PREFER_SA 00802 #undef PREFER_SB 00803 00804 void addr_delete_entry(protocol_interface_info_entry_t *cur, if_address_entry_t *addr) 00805 { 00806 if (addr->group_added) { 00807 addr_remove_solicited_node_group(cur, addr->address); 00808 } 00809 ns_list_remove(&cur->ip_addresses, addr); 00810 addr_cb(cur, addr, ADDR_CALLBACK_DELETED); 00811 ns_dyn_mem_free(addr); 00812 } 00813 00814 /* ticks is in 1/10s */ 00815 void addr_fast_timer(protocol_interface_info_entry_t *cur, uint_fast16_t ticks) 00816 { 00817 /* Fast timers only run while the interface is active. */ 00818 if (!(cur->lowpan_info & INTERFACE_NWK_ACTIVE)) { 00819 return; 00820 } 00821 00822 ns_list_foreach_safe(if_address_entry_t, addr, &cur->ip_addresses) { 00823 if (addr->state_timer == 0) { 00824 continue; 00825 } 00826 00827 if (addr->state_timer > ticks) { 00828 addr->state_timer -= ticks; 00829 continue; 00830 } 00831 00832 addr->state_timer = 0; 00833 /* Advance DAD state machine if tentative, else give it to the protocol state machine */ 00834 if (addr->tentative) { 00835 if (addr->count == 0) { 00836 #if 0 00837 // Initial join delay finished 00838 // We don't have full MLD support - send 1 report for now 00839 // This will become a real "join" later 00840 buffer_t *mld_buf; 00841 uint8_t sol_addr[16]; 00842 memcpy(sol_addr, ADDR_MULTICAST_SOLICITED, 13); 00843 memcpy(sol_addr + 13, addr->address + 13, 3); 00844 mld_buf = mld_build(cur, NULL, ICMPV6_TYPE_INFO_MCAST_LIST_REPORT, 0, sol_addr); 00845 protocol_push(mld_buf); 00846 #endif 00847 if (addr_add_solicited_node_group(cur, addr->address)) { 00848 addr->group_added = true; 00849 } 00850 } 00851 #ifdef HAVE_IPV6_ND 00852 if (addr->count >= cur->dup_addr_detect_transmits) { 00853 /* Finished - if we've not been nerfed already, we can transition 00854 * to non-tentative. 00855 */ 00856 addr->tentative = false; 00857 addr->count = 0; 00858 tr_info("DAD passed on IF %d: %s", cur->id, trace_ipv6(addr->address)); 00859 addr_cb(cur, addr, ADDR_CALLBACK_DAD_COMPLETE); 00860 } else { 00861 buffer_t *ns_buf = icmpv6_build_ns(cur, addr->address, NULL, false, true, NULL); 00862 protocol_push(ns_buf); 00863 addr->state_timer = (cur->ipv6_neighbour_cache.retrans_timer + 50) / 100; // ms -> ticks 00864 addr->count++; 00865 } 00866 #endif 00867 } else { 00868 addr_cb(cur, addr, ADDR_CALLBACK_TIMER); 00869 } 00870 00871 /* If a callback has shut down the interface, break now - this isn't 00872 * just a nicety; it avoids an iteration failure if shutdown disrupted 00873 * the address list (as is likely). 00874 */ 00875 if (!(cur->lowpan_info & INTERFACE_NWK_ACTIVE)) { 00876 break; 00877 } 00878 } 00879 } 00880 00881 void addr_slow_timer(protocol_interface_info_entry_t *cur, uint_fast16_t seconds) 00882 { 00883 /* Slow (lifetime) timers run whether the interface is active or not */ 00884 ns_list_foreach_safe(if_address_entry_t, addr, &cur->ip_addresses) { 00885 if (addr->preferred_lifetime != 0xffffffff && addr->preferred_lifetime != 0) { 00886 if (addr->preferred_lifetime > seconds) { 00887 addr->preferred_lifetime -= seconds; 00888 } else { 00889 tr_info("Address deprecated: %s", trace_ipv6(addr->address)); 00890 addr->preferred_lifetime = 0; 00891 addr_cb(cur, addr, ADDR_CALLBACK_DEPRECATED); 00892 } 00893 } 00894 00895 if (addr->valid_lifetime != 0xffffffff) { 00896 if (addr->valid_lifetime > seconds) { 00897 addr->valid_lifetime -= seconds; 00898 } else { 00899 tr_info("Address invalidated: %s", trace_ipv6(addr->address)); 00900 addr->valid_lifetime = 0; 00901 addr_cb(cur, addr, ADDR_CALLBACK_INVALIDATED); 00902 /* Give them the chance to revalidate */ 00903 if (addr->valid_lifetime == 0) { 00904 addr_delete_entry(cur, addr); 00905 } 00906 } 00907 } 00908 } 00909 00910 #ifdef MULTICAST_FORWARDING 00911 ns_list_foreach_safe(if_group_fwd_entry_t, group, &cur->ip_groups_fwd) { 00912 if (group->lifetime != 0xffffffff) { 00913 if (group->lifetime > seconds) { 00914 group->lifetime -= seconds; 00915 } else { 00916 tr_debug("MC fwd expired: %s", trace_ipv6(group->group)); 00917 addr_multicast_fwd_delete_entry(cur, group); 00918 } 00919 } 00920 } 00921 #endif 00922 } 00923 00924 static void addr_max_entries_check(protocol_interface_info_entry_t *cur, if_address_source_t source) 00925 { 00926 // Limit only auto configuration addresses 00927 if (source != ADDR_SOURCE_SLAAC || cur->ip_addresses_max_slaac_entries == 0) { 00928 return; 00929 } 00930 00931 uint8_t count = 0; 00932 if_address_entry_t *first_slaac_entry = NULL; 00933 ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) { 00934 if (e->source == ADDR_SOURCE_SLAAC) { 00935 if (!first_slaac_entry) { 00936 first_slaac_entry = e; 00937 } 00938 if (++count == 0xff) { 00939 break; 00940 } 00941 } 00942 } 00943 00944 if (count > cur->ip_addresses_max_slaac_entries) { 00945 addr_delete_entry(cur, first_slaac_entry); 00946 } 00947 } 00948 00949 void addr_max_slaac_entries_set(protocol_interface_info_entry_t *cur, uint8_t max_slaac_entries) 00950 { 00951 cur->ip_addresses_max_slaac_entries = max_slaac_entries; 00952 } 00953 00954 if_address_entry_t *addr_add(protocol_interface_info_entry_t *cur, const uint8_t address[static 16], uint_fast8_t prefix_len, if_address_source_t source, uint32_t valid_lifetime, uint32_t preferred_lifetime, bool skip_dad) 00955 { 00956 if (addr_get_entry(cur, address)) { 00957 return NULL; 00958 } 00959 00960 addr_max_entries_check(cur, source); 00961 00962 if_address_entry_t *entry = ns_dyn_mem_alloc(sizeof(if_address_entry_t)); 00963 if (!entry) { 00964 return NULL; 00965 } 00966 00967 memset(entry, 0, sizeof * entry); 00968 entry->cb = NULL; 00969 memcpy(entry->address, address, 16); 00970 entry->prefix_len = prefix_len; 00971 entry->source = source; 00972 entry->valid_lifetime = valid_lifetime; 00973 entry->preferred_lifetime = preferred_lifetime; 00974 entry->group_added = false; 00975 #ifndef HAVE_IPV6_ND 00976 skip_dad = true; 00977 #endif 00978 if (skip_dad || cur->dup_addr_detect_transmits == 0) { 00979 entry->tentative = false; 00980 if (addr_add_solicited_node_group(cur, entry->address)) { 00981 entry->group_added = true; 00982 } 00983 // XXX not right? Want to do delay + MLD join, so don't special-case? 00984 /* entry->cb isn't set yet, but global notifiers will want call */ 00985 addr_cb(cur, entry, ADDR_CALLBACK_DAD_COMPLETE); 00986 } else { 00987 entry->tentative = true; 00988 // Initial timer is for the multicast join delay 00989 entry->count = 0; 00990 entry->state_timer = randLIB_get_random_in_range(1, 10); // MAX_RTR_SOLICITATION_DELAY (1s) in ticks 00991 } 00992 00993 tr_info("%sAddress added to IF %d: %s", (entry->tentative ? "Tentative " : ""), cur->id, trace_ipv6(address)); 00994 00995 ns_list_add_to_end(&cur->ip_addresses, entry); 00996 00997 return entry; 00998 } 00999 01000 int_fast8_t addr_delete(protocol_interface_info_entry_t *cur, const uint8_t address[static 16]) 01001 { 01002 ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) { 01003 if (memcmp(e->address, address, 16) == 0) { 01004 addr_delete_entry(cur, e); 01005 return 0; 01006 } 01007 } 01008 01009 return -1; 01010 } 01011 01012 int_fast8_t addr_deprecate(protocol_interface_info_entry_t *cur, const uint8_t address[static 16]) 01013 { 01014 ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) { 01015 if (memcmp(e->address, address, 16) == 0) { 01016 tr_debug("Deprecate address %s", trace_ipv6(e->address)); 01017 addr_lifetime_update(cur, e, 0, 0, 30 * 60); //Accept max 30 min lifetime 01018 return 0; 01019 } 01020 } 01021 01022 return -1; 01023 } 01024 01025 void addr_delete_matching(protocol_interface_info_entry_t *cur, const uint8_t *prefix, uint8_t prefix_len, if_address_source_t source) 01026 { 01027 ns_list_foreach_safe(if_address_entry_t, e, &cur->ip_addresses) { 01028 if ((source == ADDR_SOURCE_UNKNOWN || e->source == source) && 01029 bitsequal(e->address, prefix, prefix_len)) { 01030 addr_delete_entry(cur, e); 01031 } 01032 } 01033 01034 } 01035 01036 void addr_set_non_preferred(protocol_interface_info_entry_t *cur, if_address_source_t source) 01037 { 01038 ns_list_foreach_safe(if_address_entry_t, e, &cur->ip_addresses) { 01039 if (e->source == source) { 01040 // Sets preferred lifetime to zero or deletes tentative addresses 01041 addr_set_preferred_lifetime(cur, e, 0); 01042 } 01043 } 01044 } 01045 01046 void addr_duplicate_detected(struct protocol_interface_info_entry *interface, const uint8_t addr[static 16]) 01047 { 01048 if_address_entry_t *entry = addr_get_entry(interface, addr); 01049 if (!entry) { 01050 return; 01051 } 01052 01053 tr_warn("DAD failed: %s", trace_ipv6(addr)); 01054 01055 interface->dad_failures++; 01056 addr_cb(interface, entry, ADDR_CALLBACK_DAD_FAILED); 01057 01058 /* Callback may have done something drastic like shut down the interface. 01059 * Don't assume entry is still valid - remove it by IP address. 01060 */ 01061 addr_delete(interface, addr); 01062 } 01063 01064 void addr_notification_register(if_address_notification_fn *fn) 01065 { 01066 ns_list_foreach(addr_notification_t, n, &addr_notifications) { 01067 if (n->fn == fn) { 01068 return; 01069 } 01070 } 01071 01072 addr_notification_t *n = ns_dyn_mem_alloc(sizeof(addr_notification_t)); 01073 if (!n) { 01074 tr_error("addr_notification_register mem"); 01075 return; 01076 } 01077 n->fn = fn; 01078 ns_list_add_to_end(&addr_notifications, n); 01079 } 01080 01081 void addr_cb(protocol_interface_info_entry_t *interface, if_address_entry_t *addr, if_address_callback_t reason) 01082 { 01083 ns_list_foreach(addr_notification_t, n, &addr_notifications) { 01084 n->fn(interface, addr, reason); 01085 } 01086 if (addr->cb) { 01087 addr->cb(interface, addr, reason); 01088 } 01089 } 01090 01091 void addr_set_valid_lifetime(protocol_interface_info_entry_t *interface, if_address_entry_t *addr, uint32_t valid_lifetime) 01092 { 01093 if (valid_lifetime != addr->valid_lifetime) { 01094 addr->valid_lifetime = valid_lifetime; 01095 addr_cb(interface, addr, ADDR_CALLBACK_REFRESHED); 01096 } 01097 } 01098 01099 void addr_set_preferred_lifetime(protocol_interface_info_entry_t *interface, if_address_entry_t *addr, uint32_t preferred_lifetime) 01100 { 01101 if (preferred_lifetime != addr->preferred_lifetime) { 01102 addr->preferred_lifetime = preferred_lifetime; 01103 if (preferred_lifetime == 0) { 01104 // Entry is deleted if it is tentative 01105 if (addr->tentative) { 01106 addr_delete_entry(interface, addr); 01107 } else { 01108 addr_cb(interface, addr, ADDR_CALLBACK_DEPRECATED); 01109 } 01110 } 01111 } 01112 } 01113 01114 void addr_lifetime_update(protocol_interface_info_entry_t *interface, if_address_entry_t *address, uint32_t valid_lifetime, uint32_t preferred_lifetime, uint32_t threshold) 01115 { 01116 //Update Current lifetimes (see RFC 4862 for rules detail) 01117 if (valid_lifetime > threshold || valid_lifetime > address->valid_lifetime) { 01118 addr_set_valid_lifetime(interface, address, valid_lifetime); 01119 } else if (address->valid_lifetime <= threshold) { 01120 //NOT Update Valid Lifetime 01121 } else { 01122 addr_set_valid_lifetime(interface, address, threshold); 01123 } 01124 01125 addr_set_preferred_lifetime(interface, address, preferred_lifetime); 01126 } 01127 01128 void memswap(uint8_t *restrict a, uint8_t *restrict b, uint_fast8_t len) 01129 { 01130 while (len--) { 01131 uint8_t t = *a; 01132 *a++ = *b; 01133 *b++ = t; 01134 } 01135 } 01136 01137 /* Optimised for quick discard of mismatching addresses (eg in a cache lookup): 01138 * searches BACKWARDS, as last bytes are most likely to differ. 01139 */ 01140 bool addr_ipv6_equal(const uint8_t a[static 16], const uint8_t b[static 16]) 01141 { 01142 for (int_fast8_t n = 15; n >= 0; n--) { 01143 if (a[n] != b[n]) { 01144 return false; 01145 } 01146 } 01147 return true; 01148 } 01149 01150 bool addr_iid_matches_eui64(const uint8_t iid[static 8], const uint8_t eui64[static 8]) 01151 { 01152 for (int_fast8_t n = 7; n >= 1; n--) { 01153 if (iid[n] != eui64[n]) { 01154 return false; 01155 } 01156 } 01157 return iid[0] == (eui64[0] ^ 2); 01158 } 01159 01160 bool addr_iid_matches_lowpan_short(const uint8_t iid[static 8], uint16_t short_addr) 01161 { 01162 if (iid[7] != (short_addr & 0xFF) || 01163 iid[6] != (short_addr >> 8)) { 01164 return false; 01165 } 01166 01167 for (int_fast8_t n = 5; n >= 0; n--) { 01168 if (iid[n] != ADDR_SHORT_ADR_SUFFIC[n]) { 01169 return false; 01170 } 01171 } 01172 return true; 01173 } 01174 01175 bool addr_iid_reserved(const uint8_t iid[static 8]) 01176 { 01177 static const uint8_t reserved_iana[5] = { 0x02, 0x00, 0x5e, 0xff, 0xfe }; 01178 static const uint8_t reserved_subnet_anycast[7] = { 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 01179 01180 if (memcmp(iid, ADDR_UNSPECIFIED + 8, 8) == 0) { 01181 return true; // subnet-router anycast 01182 } 01183 01184 if (memcmp(iid, reserved_iana, 5) == 0) { 01185 return true; 01186 } 01187 01188 if (memcmp(iid, reserved_subnet_anycast, 7) == 0 && iid[7] >= 0x80) { 01189 return true; 01190 } 01191 01192 return false; 01193 } 01194 01195 int_fast8_t addr_opaque_iid_key_set(const void *secret_key, uint8_t key_len) 01196 { 01197 /* Delete existing info */ 01198 if (addr_iid_secret_key) { 01199 ns_dyn_mem_free((void *) addr_iid_secret_key); 01200 addr_iid_secret_key = NULL; 01201 addr_iid_secret_key_len = 0; 01202 } 01203 01204 /* If disabling, that's it */ 01205 if (secret_key == NULL) { 01206 return 0; 01207 } 01208 /* Attempt to copy new info */ 01209 uint8_t *copy = ns_dyn_mem_alloc(key_len); 01210 if (!copy) { 01211 return -1; 01212 } 01213 addr_iid_secret_key = memcpy(copy, secret_key, key_len); 01214 addr_iid_secret_key_len = key_len; 01215 return 0; 01216 } 01217 01218 int_fast8_t addr_opaque_initial_iid_set(const void *iid) 01219 { 01220 /* Delete existing info */ 01221 if (addr_initial_iid) { 01222 ns_dyn_mem_free((void *) addr_initial_iid); 01223 addr_initial_iid = NULL; 01224 } 01225 if (!iid) { 01226 return 0; 01227 } 01228 /* Attempt to copy new info */ 01229 uint8_t *copy = ns_dyn_mem_alloc(8); 01230 if (!copy) { 01231 return -1; 01232 } 01233 addr_initial_iid = memcpy(copy, iid, 8); 01234 return 0; 01235 } 01236 01237 bool addr_opaque_iid_key_is_set(void) 01238 { 01239 return addr_iid_secret_key != NULL; 01240 } 01241 01242 /* RFC 7217 generation: addr must be prepopulated with 8-byte prefix, and secret key must be set */ 01243 void addr_generate_opaque_iid(protocol_interface_info_entry_t *cur, uint8_t addr[static 16]) 01244 { 01245 opaque_retry: 01246 01247 if (addr_initial_iid && !cur->dad_failures) { 01248 // This is test implementations use only normally should not need this. 01249 memcpy(addr + 8, addr_initial_iid, 8); 01250 return; 01251 } 01252 { 01253 // Limit scope to try to minimise stack, given the goto 01254 ns_sha256_context ctx; 01255 ns_sha256_init(&ctx); 01256 ns_sha256_starts(&ctx); 01257 ns_sha256_update(&ctx, addr, 8); 01258 if (cur->interface_name) { 01259 /* This isn't ideal - there's no guarantee each instance of a driver has a distinct name */ 01260 ns_sha256_update(&ctx, cur->interface_name, strlen(cur->interface_name)); 01261 } else { 01262 ns_sha256_update(&ctx, &cur->id, sizeof cur->id); 01263 } 01264 ns_sha256_update(&ctx, &cur->dad_failures, sizeof cur->dad_failures); 01265 ns_sha256_update(&ctx, addr_iid_secret_key, addr_iid_secret_key_len); 01266 ns_sha256_finish_nbits(&ctx, addr + 8, 64); 01267 ns_sha256_free(&ctx); 01268 } 01269 /* Note that we only check for reserved IIDs - as per RFC 7217, 01270 * there's no restriction on U/G bits. 01271 */ 01272 if (addr_iid_reserved(addr + 8)) { 01273 cur->dad_failures++; 01274 goto opaque_retry; 01275 } 01276 } 01277 01278 /* Write a LoWPAN IPv6 address, based on a prefix and short address */ 01279 uint8_t *addr_ipv6_write_from_lowpan_short(uint8_t dst[static 16], const uint8_t prefix[static 8], uint16_t short_addr) 01280 { 01281 common_write_16_bit(short_addr, dst + 14); 01282 memcpy(dst + 8, ADDR_SHORT_ADR_SUFFIC, 6); 01283 return memcpy(dst, prefix, 8); 01284 } 01285 01286 /* Turn an address (either MAC or IP) into a base IP address for context compression */ 01287 bool addr_iid_from_outer(uint8_t iid_out[static 8], const sockaddr_t *addr_in) 01288 { 01289 switch (addr_in->addr_type ) { 01290 case ADDR_802_15_4_LONG : 01291 memcpy(iid_out, addr_in->address + 2, 8); 01292 iid_out[0] ^= 2; 01293 break; 01294 case ADDR_BROADCAST : 01295 case ADDR_802_15_4_SHORT : 01296 memcpy(iid_out, ADDR_SHORT_ADR_SUFFIC, 6); 01297 iid_out[6] = addr_in->address [2]; 01298 iid_out[7] = addr_in->address [3]; 01299 break; 01300 case ADDR_IPV6 : 01301 memcpy(iid_out, addr_in->address + 8, 8); 01302 break; 01303 default: 01304 return false; 01305 } 01306 01307 return true; 01308 } 01309 01310 int addr_interface_set_ll64(protocol_interface_info_entry_t *cur, if_address_callback_fn *cb) 01311 { 01312 int ret_val = -1; 01313 if_address_entry_t *address_entry = NULL; 01314 uint8_t temp_ll64[16]; 01315 memcpy(temp_ll64, ADDR_LINK_LOCAL_PREFIX, 8); 01316 memcpy(temp_ll64 + 8, cur->iid_eui64, 8); 01317 01318 address_entry = addr_add(cur, temp_ll64, 64, ADDR_SOURCE_UNKNOWN, 0xffffffff, 0xffffffff, false); 01319 if (address_entry) { 01320 tr_debug("LL64 Register OK!"); 01321 ret_val = 0; 01322 address_entry->cb = cb; 01323 if (!address_entry->tentative) { 01324 addr_cb(cur, address_entry, ADDR_CALLBACK_DAD_COMPLETE); 01325 } 01326 } 01327 return ret_val; 01328 } 01329 01330 /* address_type 0 means "any" address - we return short by preference */ 01331 /* address_type 1 means long address - we ignore short addresses */ 01332 int8_t addr_interface_get_ll_address(protocol_interface_info_entry_t *cur, uint8_t *address_ptr, uint8_t address_type) 01333 { 01334 const uint8_t *short_addr = NULL; 01335 const uint8_t *long_addr = NULL; 01336 01337 if (!cur) { 01338 return -1; 01339 } 01340 01341 ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) { 01342 if (!e->tentative && addr_is_ipv6_link_local(e->address)) { 01343 if (cur->nwk_id == IF_6LoWPAN && memcmp(e->address + 8, ADDR_SHORT_ADR_SUFFIC, 6) == 0) { 01344 short_addr = e->address; 01345 } else { 01346 long_addr = e->address; 01347 } 01348 01349 if (long_addr && short_addr) { 01350 break; 01351 } 01352 } 01353 } 01354 01355 if (short_addr && address_type != 1) { 01356 if (address_ptr) { 01357 memcpy(address_ptr, short_addr, 16); 01358 } 01359 return 0; 01360 } else if (long_addr) { 01361 if (address_ptr) { 01362 memcpy(address_ptr, long_addr, 16); 01363 } 01364 return 0; 01365 } else { 01366 return -1; 01367 } 01368 } 01369 01370 bool addr_interface_all_address_ready(protocol_interface_info_entry_t *cur) 01371 { 01372 if (!cur) { 01373 return false; 01374 } 01375 01376 ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) { 01377 if (e->tentative) { 01378 return false; 01379 } 01380 } 01381 return true; 01382 } 01383 01384 int8_t addr_interface_gp_prefix_compare(protocol_interface_info_entry_t *cur, const uint8_t *prefix) 01385 { 01386 if (cur->global_address_available) { 01387 ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) { 01388 if (memcmp(e->address, prefix, 8) == 0) { 01389 return 0; 01390 } 01391 } 01392 } 01393 return -1; 01394 } 01395 01396 int8_t addr_interface_address_compare(protocol_interface_info_entry_t *cur, const uint8_t *addr) 01397 { 01398 /* First check the specified interface */ 01399 if (addr_is_assigned_to_interface(cur, addr)) { 01400 return 0; 01401 } 01402 01403 /* Then check other interfaces, enforcing scope zones */ 01404 uint_fast8_t scope = addr_ipv6_scope(addr, cur); 01405 ns_list_foreach(protocol_interface_info_entry_t, other, &protocol_interface_info_list) { 01406 if (other != cur && 01407 other->zone_index[scope] == cur->zone_index[scope] && 01408 addr_is_assigned_to_interface(other, addr)) { 01409 // special handling for Thread - external global-scope ULA coming in, 01410 // which would match, but we need to restrict if that ULA is mesh-local 01411 // on the Thread side. 01412 if (thread_info(other) && addr_ipv6_scope(addr, other) <= IPV6_SCOPE_REALM_LOCAL) { 01413 continue; 01414 } 01415 return 0; 01416 } 01417 } 01418 01419 return -1; 01420 } 01421 01422 int8_t addr_interface_select_source(protocol_interface_info_entry_t *cur, uint8_t *src_ptr, const uint8_t *dest, uint32_t addr_preferences) 01423 { 01424 int8_t ret_val = -1; 01425 if (cur) { 01426 const uint8_t *src = addr_select_source(cur, dest, addr_preferences); 01427 if (src) { 01428 memcpy(src_ptr, src, 16); 01429 ret_val = 0; 01430 } 01431 } 01432 return ret_val; 01433 } 01434 01435 void addr_policy_remove_by_label(uint8_t label) 01436 { 01437 ns_list_foreach_safe(addr_policy_table_entry_t, entry, &addr_policy_table) { 01438 if (entry->label == label) { 01439 /* 01440 * Remove label policy if no local address matches" 01441 */ 01442 if (!protocol_interface_any_address_match(entry->prefix, entry->prefix_len)) { 01443 ns_list_remove(&addr_policy_table, entry); 01444 ns_dyn_mem_free(entry); 01445 } 01446 } 01447 } 01448 } 01449 01450 // This last function must always be compiled with tracing enabled 01451 #ifndef FEA_TRACE_SUPPORT 01452 #define FEA_TRACE_SUPPORT 1 01453 #include "mbed-trace/mbed_trace.h" 01454 #endif 01455 char *trace_sockaddr(const sockaddr_t *addr, bool panid_prefix) 01456 { 01457 uint8_t length = addr_len_from_type(addr->addr_type ); 01458 01459 if (length == 0) { 01460 return "<n/a>"; 01461 } 01462 01463 /* Awkward hack for 802.15.4 address types */ 01464 if (addr->addr_type == ADDR_802_15_4_SHORT || 01465 addr->addr_type == ADDR_802_15_4_LONG ) { 01466 length -= (panid_prefix) ? 0 : 2; 01467 } 01468 01469 /* Start from index 0 (prints PAN ID if exists) */ 01470 return trace_array(&addr->address [0], length); 01471 }
Generated on Tue Jul 12 2022 13:54:38 by
