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
icmpv6.c
00001 /* 00002 * Copyright (c) 2013-2019, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 #include "nsconfig.h" 00018 #include "ns_types.h" 00019 #include "string.h" 00020 #include "ns_trace.h" 00021 #include "randLIB.h" 00022 #include "NWK_INTERFACE/Include/protocol.h" 00023 #include "RPL/rpl_control.h" 00024 #ifdef HAVE_RPL 00025 #include "RPL/rpl_data.h" 00026 #endif 00027 #include "RPL/rpl_protocol.h" 00028 #ifdef HAVE_MPL 00029 #include "MPL/mpl.h" 00030 #endif 00031 #include "Common_Protocols/icmpv6.h" 00032 #include "Common_Protocols/icmpv6_prefix.h" 00033 #include "Common_Protocols/icmpv6_radv.h" 00034 #include "Common_Protocols/ip.h" 00035 #include "Common_Protocols/ipv6.h" 00036 #include "Common_Protocols/mld.h" 00037 #include "Core/include/ns_socket.h" 00038 #include "ipv6_stack/protocol_ipv6.h" 00039 #include "ipv6_stack/ipv6_routing_table.h" 00040 #include "ip_fsc.h" 00041 #include "ipv6_stack/ipv6_routing_table.h" 00042 #include "Service_Libs/nd_proxy/nd_proxy.h" 00043 #include "NWK_INTERFACE/Include/protocol_stats.h" 00044 #include "common_functions.h" 00045 #include "6LoWPAN/ND/nd_router_object.h" 00046 #include "6LoWPAN/Bootstraps/protocol_6lowpan.h" 00047 #include "6LoWPAN/ws/ws_common_defines.h" 00048 #include "6LoWPAN/ws/ws_common.h" 00049 00050 #define TRACE_GROUP "icmp" 00051 00052 static buffer_t *icmpv6_echo_request_handler(struct buffer *buf); 00053 00054 /* Check to see if a message is recognisable ICMPv6, and if so, fill in code/type */ 00055 /* This used ONLY for the e.1 + e.2 tests in RFC 4443, to try to avoid ICMPv6 error loops */ 00056 /* Packet may be ill-formed, because we are considering an ICMPv6 error response. */ 00057 static bool is_icmpv6_msg(buffer_t *buf) 00058 { 00059 const uint8_t *ptr = buffer_data_pointer(buf); 00060 uint16_t len = buffer_data_length(buf); 00061 00062 /* IP header format: 00063 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00064 * |Version| Traffic Class | Flow Label | 00065 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00066 * | Payload Length | Next Header | Hop Limit | 00067 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00068 * + Source Address (16) + Destination Address (16), total 40 00069 */ 00070 if (len < IPV6_HDRLEN) { 00071 return false; 00072 } 00073 uint16_t ip_len = common_read_16_bit(ptr + IPV6_HDROFF_PAYLOAD_LENGTH); 00074 uint8_t nh = ptr[IPV6_HDROFF_NH]; 00075 ptr += IPV6_HDRLEN; 00076 len -= IPV6_HDRLEN; 00077 if (ip_len > len) { 00078 return false; 00079 } 00080 len = ip_len; 00081 while (len) { 00082 uint16_t hdrlen; 00083 switch (nh) { 00084 case IPV6_NH_ICMPV6: 00085 if (len < 4) { 00086 return false; 00087 } 00088 buf->options .type = ptr[0]; 00089 buf->options .code = ptr[1]; 00090 return true; 00091 case IPV6_NH_HOP_BY_HOP: 00092 case IPV6_NH_DEST_OPT: 00093 case IPV6_NH_ROUTING: 00094 case IPV6_NH_MOBILITY: 00095 case IPV6_NH_HIP: 00096 case IPV6_NH_SHIM6: 00097 if (len < 8) { 00098 return false; 00099 } 00100 nh = ptr[0]; 00101 hdrlen = (ptr[1] + 1) * 8; 00102 break; 00103 case IPV6_NH_AUTH: 00104 if (len < 8) { 00105 return false; 00106 } 00107 nh = ptr[0]; 00108 hdrlen = (ptr[1] + 2) * 4; 00109 break; 00110 default: 00111 return false; 00112 } 00113 if (hdrlen > len || (hdrlen & 7)) { 00114 return false; 00115 } 00116 ptr += hdrlen; 00117 len -= hdrlen; 00118 } 00119 return false; 00120 } 00121 00122 buffer_t *icmpv6_error(buffer_t *buf, protocol_interface_info_entry_t *cur, uint8_t type, uint8_t code, uint32_t aux) 00123 { 00124 uint8_t *ptr; 00125 00126 /* Don't send ICMP errors to improperly-secured packets (they either reach MLE etc successfully, or we just drop) */ 00127 if (buf->options .ll_security_bypass_rx ) { 00128 return buffer_free(buf); 00129 } 00130 00131 if (cur == NULL) { 00132 cur = buf->interface ; 00133 } 00134 00135 /* Any ICMPv6 error in response to an UP packet implies an RX drop... */ 00136 if ((buf->info & B_DIR_MASK) == B_DIR_UP) { 00137 protocol_stats_update(STATS_IP_RX_DROP, 1); 00138 } 00139 00140 /* RFC 4443 processing rules e.1-2: don't send errors for ICMPv6 errors or redirects */ 00141 if (is_icmpv6_msg(buf) && (buf->options .type < 128 || buf->options .type == ICMPV6_TYPE_INFO_REDIRECT)) { 00142 return buffer_free(buf); 00143 } 00144 00145 /* RFC 4443 processing rules e.3-5: don't send errors for IP multicasts or link-layer multicasts+broadcasts (with exceptions) */ 00146 if (addr_is_ipv6_multicast(buf->dst_sa .address ) || buf->options .ll_broadcast_rx || buf->options .ll_multicast_rx ) { 00147 if (!(type == ICMPV6_TYPE_ERROR_PACKET_TOO_BIG || 00148 (type == ICMPV6_TYPE_ERROR_PARAMETER_PROBLEM && code == ICMPV6_CODE_PARAM_PRB_UNREC_IPV6_OPT))) { 00149 return buffer_free(buf); 00150 } 00151 } 00152 00153 /* RFC 4443 processing rule e.6 - source doesn't identify a single node */ 00154 if (addr_is_ipv6_unspecified(buf->src_sa .address ) || addr_is_ipv6_multicast(buf->src_sa .address )) { 00155 return buffer_free(buf); 00156 } 00157 00158 if (addr_interface_address_compare(cur, buf->dst_sa .address ) == 0) { 00159 // RFC 4443 2.2 - if addressed to us, use that address as source 00160 memswap(buf->dst_sa .address , buf->src_sa .address , 16); 00161 } else { 00162 // Otherwise we will use normal address selection rule 00163 buf->dst_sa = buf->src_sa ; 00164 00165 // This makes buffer_route choose the address 00166 buf->src_sa .addr_type = ADDR_NONE ; 00167 } 00168 00169 buffer_turnaround(buf); 00170 00171 if (!ipv6_buffer_route(buf)) { 00172 return buffer_free(buf); 00173 } 00174 cur = buf->interface ; 00175 00176 /* Token-bucket rate limiting */ 00177 if (!cur->icmp_tokens) { 00178 return buffer_free(buf); 00179 } 00180 cur->icmp_tokens--; 00181 00182 /* Include as much of the original packet as possible, without exceeding 00183 * minimum MTU of 1280. */ 00184 uint16_t max_payload = ipv6_max_unfragmented_payload(buf, IPV6_MIN_LINK_MTU); 00185 if (buffer_data_length(buf) > max_payload - 8) { 00186 buffer_data_length_set(buf, max_payload - 8); 00187 } 00188 00189 if ((buf = buffer_headroom(buf, 4)) == NULL) { 00190 return NULL; 00191 } 00192 ptr = buffer_data_reserve_header(buf, 4); 00193 ptr = common_write_32_bit(aux, ptr); 00194 buf->options .traffic_class = 0; 00195 buf->options .type = type; 00196 buf->options .code = code; 00197 buf->options .hop_limit = cur->cur_hop_limit; 00198 buf->info = (buffer_info_t)(B_FROM_ICMP | B_TO_ICMP | B_DIR_DOWN); 00199 00200 return (buf); 00201 } 00202 00203 #ifndef NO_IPV6_PMTUD 00204 /* Look at a (potentially-partial) packet that should be a copy of 00205 * something we sent from an ICMP error. Identify final destination if we can. 00206 */ 00207 static bool icmpv6_identify_final_destination(buffer_t *buf, uint8_t *dest) 00208 { 00209 const uint8_t *ptr = buffer_data_pointer(buf); 00210 00211 /* Start with destination in IP header */ 00212 memcpy(dest, ptr + 24, 16); 00213 #ifdef HAVE_RPL 00214 /* Have to look for routing header */ 00215 uint8_t nh = ptr[6]; 00216 uint16_t hlen = 40; 00217 uint16_t len = buffer_data_length(buf); 00218 ptr += 40; 00219 len -= 40; 00220 for (;;) { 00221 if (len < hlen) { 00222 return false; 00223 } 00224 ptr += hlen; 00225 len -= hlen; 00226 00227 /* Only need to process stuff we can send... */ 00228 switch (nh) { 00229 case IPV6_NH_HOP_BY_HOP: 00230 case IPV6_NH_DEST_OPT: 00231 if (len < 2) { 00232 return false; 00233 } 00234 hlen = (ptr[1] + 1) * 8; 00235 nh = ptr[0]; 00236 break; 00237 case IPV6_NH_ROUTING: 00238 if (len < 4) { 00239 return false; 00240 } 00241 /* If segments left is zero, IP dest is okay */ 00242 if (ptr[3] == 0) { 00243 return true; 00244 } 00245 if (ptr[2] != IPV6_ROUTING_TYPE_RPL) { 00246 return false; 00247 } 00248 hlen = (ptr[1] + 1) * 8; 00249 if (len < hlen) { 00250 return false; 00251 } 00252 return rpl_data_get_srh_last_address(ptr, dest); 00253 case IPV6_NH_FRAGMENT: 00254 case IPV6_NH_IPV6: 00255 case IPV6_NH_ICMPV6: 00256 case IPV6_NH_UDP: 00257 case IPV6_NH_TCP: 00258 /* If we've reached this header, it's too late for routing */ 00259 return true; 00260 default: 00261 /* Unrecognised header - can't have come from us... */ 00262 return false; 00263 } 00264 } 00265 #else 00266 return true; 00267 #endif 00268 } 00269 00270 buffer_t *icmpv6_packet_too_big_handler(buffer_t *buf) 00271 { 00272 tr_info("ICMP packet too big from: %s", trace_ipv6(buf->src_sa .address )); 00273 00274 /* Need 4 for MTU, plus at least the IP header */ 00275 if (buffer_data_length(buf) < 4 + 40) { 00276 return buffer_free(buf); 00277 } 00278 00279 protocol_interface_info_entry_t *cur = buf->interface ; 00280 00281 const uint8_t *ptr = buffer_data_pointer(buf); 00282 uint32_t mtu = common_read_32_bit(ptr); 00283 00284 /* RFC 8201 - ignore MTU smaller than minimum */ 00285 if (mtu < IPV6_MIN_LINK_MTU) { 00286 return buffer_free(buf); 00287 } 00288 00289 ptr = buffer_data_strip_header(buf, 4); 00290 00291 /* Check source is us */ 00292 if (addr_interface_address_compare(cur, ptr + 8)) { 00293 return buffer_free(buf); 00294 } 00295 00296 uint8_t final_dest[16]; 00297 if (!icmpv6_identify_final_destination(buf, final_dest)) { 00298 return buffer_free(buf); 00299 } 00300 00301 ipv6_destination_t *dest = ipv6_destination_lookup_or_create(final_dest, cur->id); 00302 00303 if (dest && mtu < dest->pmtu) { 00304 00305 tr_info("Reducing PMTU to %"PRIu32" for: %s", mtu, trace_ipv6(final_dest)); 00306 dest->pmtu = mtu; 00307 dest->pmtu_lifetime = cur->pmtu_lifetime; 00308 } 00309 00310 return buffer_free(buf); 00311 } 00312 #endif 00313 00314 static buffer_t *icmpv6_echo_request_handler(buffer_t *buf) 00315 { 00316 protocol_interface_info_entry_t *cur = buf->interface ; 00317 if (!cur) { 00318 return buffer_free(buf); 00319 } 00320 00321 buf->info = (buffer_info_t)(B_FROM_ICMP | B_TO_ICMP | B_DIR_DOWN); 00322 buf->options .type = ICMPV6_TYPE_INFO_ECHO_REPLY; 00323 buf->options .code = 0x00; 00324 buf->options .hop_limit = cur->cur_hop_limit; 00325 00326 if (addr_is_ipv6_multicast(buf->dst_sa .address )) { 00327 const uint8_t *ipv6_ptr; 00328 memcpy(buf->dst_sa .address , buf->src_sa .address , 16); 00329 ipv6_ptr = addr_select_source(cur, buf->dst_sa .address , 0); 00330 if (!ipv6_ptr) { 00331 tr_debug("No address"); 00332 return buffer_free(buf); 00333 } 00334 memcpy(buf->src_sa .address , ipv6_ptr, 16); 00335 } else { 00336 memswap(buf->dst_sa .address , buf->src_sa .address , 16); 00337 } 00338 00339 return buffer_turnaround(buf); 00340 } 00341 00342 #ifdef HAVE_IPV6_ND 00343 00344 static void icmpv6_na_wisun_aro_handler(protocol_interface_info_entry_t *cur_interface, const uint8_t *dptr, const uint8_t *src_addr) 00345 { 00346 (void) src_addr; 00347 dptr += 2; 00348 uint16_t life_time; 00349 uint8_t nd_status = *dptr; 00350 dptr += 4; 00351 life_time = common_read_16_bit(dptr); 00352 dptr += 2; 00353 if (memcmp(dptr, cur_interface->mac, 8) != 0) { 00354 return; 00355 } 00356 00357 (void)life_time; 00358 if (nd_status != ARO_SUCCESS) { 00359 ws_common_aro_failure(cur_interface, src_addr, true); 00360 } 00361 } 00362 00363 static void icmpv6_na_aro_handler(protocol_interface_info_entry_t *cur_interface, const uint8_t *dptr, const uint8_t *dst_addr) 00364 { 00365 (void)dst_addr; 00366 dptr += 2; 00367 uint16_t life_time; 00368 uint8_t nd_status = *dptr; 00369 dptr += 4; 00370 life_time = common_read_16_bit(dptr); 00371 dptr += 2; 00372 if (memcmp(dptr, cur_interface->mac, 8) != 0) { 00373 return; 00374 } 00375 00376 /* Failure responses go to LL64, and they thus don't actually indicate the 00377 * address that we were trying to register. So we have to rely on having 00378 * "current DAD address" stored. We don't get it from the packet in any case. 00379 */ 00380 if (!cur_interface->if_6lowpan_dad_process.active) { 00381 return; 00382 } 00383 00384 if_address_entry_t *addr_entry = addr_get_entry(cur_interface, cur_interface->if_6lowpan_dad_process.address); 00385 if (!addr_entry) { 00386 return; 00387 } 00388 00389 switch (nd_status) { 00390 case ARO_SUCCESS: 00391 addr_cb(cur_interface, addr_entry, ADDR_CALLBACK_DAD_COMPLETE); 00392 if (addr_entry->cb) { 00393 /* Lifetime is in minutes, state_timer in 1/10 s: a factor of 600 */ 00394 /* Set renewal to 75-85% of full lifetime by multiplying by [450..510] */ 00395 addr_entry->state_timer = life_time * randLIB_get_random_in_range(450, 510); 00396 } 00397 00398 break; 00399 00400 case ARO_DUPLICATE: 00401 addr_duplicate_detected(cur_interface, addr_entry->address); 00402 break; 00403 00404 case ARO_FULL: 00405 addr_cb(cur_interface, addr_entry, ADDR_CALLBACK_PARENT_FULL); 00406 break; 00407 } 00408 } 00409 00410 /* 00411 * Neighbor Solicitation Message Format 00412 * 00413 * 0 1 2 3 00414 * 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 00415 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00416 * | Type | Code | Checksum | 00417 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00418 * | Reserved | 00419 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00420 * | | 00421 * + + 00422 * | | 00423 * + Target Address + 00424 * | | 00425 * + + 00426 * | | 00427 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00428 * | Options ... 00429 * +-+-+-+-+-+-+-+-+-+-+-+- 00430 * 00431 * 00432 * Source/Target Link-layer Address 00433 * 00434 * 0 1 2 3 00435 * 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 00436 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00437 * | Type | Length | Link-Layer Address ... 00438 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00439 * 00440 */ 00441 static buffer_t *icmpv6_ns_handler(buffer_t *buf) 00442 { 00443 protocol_interface_info_entry_t *cur; 00444 uint8_t target[16]; 00445 uint8_t dummy_sllao[16]; 00446 bool proxy = false; 00447 const uint8_t *sllao; 00448 const uint8_t *aro; 00449 uint8_t *dptr = buffer_data_pointer(buf); 00450 aro_t aro_out = { .present = false }; 00451 00452 cur = buf->interface ; 00453 00454 if (buf->options .code != 0 || buf->options .hop_limit != 255) { 00455 goto drop; 00456 } 00457 00458 if (!icmpv6_options_well_formed_in_buffer(buf, 20)) { 00459 goto drop; 00460 } 00461 00462 sllao = icmpv6_find_option_in_buffer(buf, 20, ICMPV6_OPT_SRC_LL_ADDR, 0); 00463 00464 /* If no SLLAO, ignore ARO (RFC 6775 6.5) */ 00465 /* This rule can be bypassed by setting flag "use_eui64_as_slla_in_aro" to true */ 00466 if (cur->ipv6_neighbour_cache.recv_addr_reg && 00467 (cur->ipv6_neighbour_cache.use_eui64_as_slla_in_aro || sllao)) { 00468 aro = icmpv6_find_option_in_buffer(buf, 20, ICMPV6_OPT_ADDR_REGISTRATION, 0); 00469 } else { 00470 aro = NULL; 00471 } 00472 00473 /* ARO's length must be 2 and status must be 0 */ 00474 if (aro && (aro[1] != 2 || aro[2] != 0)) { 00475 goto drop; 00476 } 00477 00478 /* If there was no SLLAO on ARO, use mac address to create dummy one... */ 00479 if (aro && !sllao && cur->ipv6_neighbour_cache.use_eui64_as_slla_in_aro) { 00480 dummy_sllao[0] = ICMPV6_OPT_SRC_LL_ADDR; // Type 00481 dummy_sllao[1] = 2; // Length = 2x8 bytes 00482 memcpy(dummy_sllao + 2, aro + 8, 8); // EUI-64 00483 memset(dummy_sllao + 10, 0, 6); // Padding 00484 00485 sllao = dummy_sllao; 00486 } 00487 // Skip the 4 reserved bytes 00488 dptr += 4; 00489 00490 // Copy the target IPv6 address 00491 memcpy(target, dptr, 16); 00492 dptr += 16; 00493 00494 if (addr_is_ipv6_multicast(target)) { 00495 goto drop; 00496 } 00497 00498 if (addr_is_ipv6_unspecified(buf->src_sa .address )) { 00499 /* Dest must be to solicited-node multicast, without source LL-addr */ 00500 if (sllao || memcmp(buf->dst_sa .address , ADDR_MULTICAST_SOLICITED, 13) != 0) { 00501 goto drop; 00502 } 00503 00504 /* If unspecified source, ignore ARO (RFC 6775 6.5) */ 00505 aro = NULL; 00506 } 00507 00508 /* See RFC 4862 5.4.3 - hook for Duplicate Address Detection */ 00509 if (addr_is_tentative_for_interface(cur, target)) { 00510 if (addr_is_ipv6_unspecified(buf->src_sa .address )) { 00511 tr_debug("Received DAD NS for our tentative address"); 00512 /* Someone else is performing DAD */ 00513 addr_duplicate_detected(cur, target); 00514 } 00515 goto drop; 00516 } 00517 00518 /* This first check's a bit dodgy - it responds to our address on the other 00519 * interface, which we should only do in the whiteboard case. 00520 */ 00521 if (addr_interface_address_compare(cur, target) != 0) { 00522 //tr_debug("Received NS for proxy %s", trace_ipv6(target)); 00523 00524 proxy = true; 00525 //Filter Link Local scope 00526 if (addr_is_ipv6_link_local(target)) { 00527 goto drop; 00528 } 00529 00530 if (!nd_proxy_enabled_for_downstream(cur->id) || !nd_proxy_target_address_validation(cur->id, target)) { 00531 goto drop; 00532 } 00533 } 00534 00535 if (aro) { 00536 /* If it had an ARO, and we're paying attention to it, possibilities: 00537 * 1) No reply to NS now, we need to contact border router (false return) 00538 * 2) Reply to NS now, with ARO (true return, aro_out.present true) 00539 * 3) Reply to NS now, without ARO (true return, aro_out.present false) 00540 */ 00541 if (!nd_ns_aro_handler(cur, aro, sllao, buf->src_sa .address , &aro_out)) { 00542 goto drop; 00543 } 00544 } 00545 00546 /* If we're returning an ARO, then we assume the ARO handler has done the 00547 * necessary to the Neighbour Cache. Otherwise, normal RFC 4861 processing. */ 00548 if (!aro_out.present && 00549 sllao && cur->if_llao_parse(cur, sllao, &buf->dst_sa )) { 00550 ipv6_neighbour_update_unsolicited(&cur->ipv6_neighbour_cache, buf->src_sa .address , buf->dst_sa .addr_type , buf->dst_sa .address ); 00551 } 00552 00553 buffer_t *na_buf = icmpv6_build_na(cur, true, !proxy, addr_is_ipv6_multicast(buf->dst_sa .address ), target, aro_out.present ? &aro_out : NULL, buf->src_sa .address ); 00554 00555 buffer_free(buf); 00556 00557 return na_buf; 00558 00559 drop: 00560 buf = buffer_free(buf); 00561 00562 return buf; 00563 00564 } 00565 00566 int icmpv6_slaac_prefix_update(struct protocol_interface_info_entry *cur, const uint8_t *prefix_ptr, uint8_t prefix_len, uint32_t valid_lifetime, uint32_t preferred_lifetime) 00567 { 00568 int ret_val = -1; 00569 00570 //Validate first current list If prefix is already defined adress 00571 ns_list_foreach_safe(if_address_entry_t, e, &cur->ip_addresses) { 00572 if (e->source == ADDR_SOURCE_SLAAC && (e->prefix_len == prefix_len) && bitsequal(e->address, prefix_ptr, prefix_len)) { 00573 00574 addr_lifetime_update(cur, e, valid_lifetime, preferred_lifetime, 2 * 60 * 60); 00575 ret_val = 0; 00576 } 00577 } 00578 return ret_val; 00579 } 00580 00581 void icmpv6_slaac_prefix_register_trig(struct protocol_interface_info_entry *cur, uint8_t *prefix_ptr, uint8_t prefix_len) 00582 { 00583 00584 //Validate first current list If prefix is already defined adress 00585 ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) { 00586 if (e->source == ADDR_SOURCE_SLAAC && (e->prefix_len == prefix_len) && bitsequal(e->address, prefix_ptr, prefix_len)) { 00587 e->state_timer = 150; 00588 } 00589 } 00590 } 00591 #endif // HAVE_IPV6_ND 00592 00593 if_address_entry_t *icmpv6_slaac_address_add(protocol_interface_info_entry_t *cur, const uint8_t *prefix_ptr, uint8_t prefix_len, uint32_t valid_lifetime, uint32_t preferred_lifetime, bool skip_dad, slaac_src_e slaac_src) 00594 { 00595 if_address_entry_t *address_entry; 00596 uint8_t ipv6_address[16]; 00597 //define Autonomous address generation 00598 00599 if (prefix_len != 64) { 00600 return NULL; 00601 } 00602 00603 if (slaac_src == SLAAC_IID_DEFAULT && cur->opaque_slaac_iids && addr_opaque_iid_key_is_set()) { 00604 slaac_src = SLAAC_IID_OPAQUE; 00605 } 00606 00607 memcpy(ipv6_address, prefix_ptr, 8); 00608 switch (slaac_src) { 00609 case SLAAC_IID_DEFAULT: 00610 case SLAAC_IID_FIXED: 00611 memcpy(ipv6_address + 8, cur->iid_slaac, 8); 00612 break; 00613 case SLAAC_IID_EUI64: 00614 memcpy(ipv6_address + 8, cur->iid_eui64, 8); 00615 break; 00616 case SLAAC_IID_OPAQUE: 00617 addr_generate_opaque_iid(cur, ipv6_address); 00618 break; 00619 case SLAAC_IID_6LOWPAN_SHORT: 00620 if (cur->nwk_id != IF_6LoWPAN || !cur->mac_parameters) { 00621 return NULL; 00622 } 00623 memcpy(ipv6_address + 8, ADDR_SHORT_ADR_SUFFIC, 6); 00624 common_write_16_bit(cur->lowpan_desired_short_address, ipv6_address + 14); 00625 break; 00626 00627 default: 00628 return NULL; 00629 } 00630 00631 //tr_debug("Add add: %s", trace_ipv6(ipv6_address)); 00632 00633 address_entry = addr_add(cur, ipv6_address, 64, ADDR_SOURCE_SLAAC, valid_lifetime, preferred_lifetime, skip_dad); 00634 if (address_entry) { 00635 address_entry->cb = NULL; 00636 } 00637 return address_entry; 00638 } 00639 00640 #ifdef HAVE_IPV6_ND 00641 static buffer_t *icmpv6_ra_handler(buffer_t *buf) 00642 { 00643 protocol_interface_info_entry_t *cur; 00644 uint8_t flags, hoplimit; 00645 uint32_t reachable_time, retrans_timer; 00646 uint16_t data_len, router_lifetime; 00647 uint8_t *dptr; 00648 ipv6_neighbour_t *ncache_entry = NULL; 00649 int_fast8_t preference = 0; 00650 uint32_t longest_route_lifetime = 0; 00651 00652 if (!buf) { 00653 return NULL; 00654 } 00655 00656 cur = buf->interface ; 00657 00658 // If both route and prefix receive are disabled do not process any RA options 00659 if (!cur->recv_ra_routes && !cur->recv_ra_prefixes) { 00660 return buffer_free(buf); 00661 } 00662 00663 // Drop RA If LL address generation is not ready 00664 if (addr_interface_get_ll_address(cur, NULL, 0) < 0) { 00665 return buffer_free(buf); 00666 } 00667 00668 if (cur->nwk_id == IF_6LoWPAN) { 00669 // XXX this check needs to be for host bootstrap only 00670 if ((cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) == 0) { 00671 if (protocol_6lowpan_interface_compare_cordinator_netid(cur, &(buf->src_sa .address [8])) != 0) { 00672 return buffer_free(buf); 00673 } 00674 } 00675 } 00676 00677 if (!addr_is_ipv6_link_local(buf->src_sa .address ) || buf->options .hop_limit != 255 || buf->options .code != 0) { 00678 return buffer_free(buf); 00679 } 00680 00681 if (!icmpv6_options_well_formed_in_buffer(buf, 12)) { 00682 tr_debug("Malformed RA"); 00683 return buffer_free(buf); 00684 } 00685 00686 /* Token-bucket rate limiting */ 00687 if (!cur->icmp_ra_tokens) { 00688 return buffer_free(buf); 00689 } 00690 cur->icmp_ra_tokens--; 00691 00692 data_len = buffer_data_length(buf); 00693 dptr = buffer_data_pointer(buf); 00694 //tr_debug("RX RA: %s", trace_ipv6(buf->src_sa.address)); 00695 00696 /* XXX we always set variables based on RAs; fine for a host, 00697 * but wrong/iffy for a router. But then so is doing SLAAC as a 00698 * router... 00699 */ 00700 hoplimit = *dptr++; 00701 if (hoplimit) { 00702 cur->cur_hop_limit = hoplimit; 00703 } 00704 00705 //Read Flags 00706 flags = *dptr++; 00707 router_lifetime = common_read_16_bit(dptr); 00708 dptr += 2; 00709 00710 reachable_time = common_read_32_bit(dptr); 00711 dptr += 4; 00712 if (reachable_time != 0 && reachable_time != cur->base_reachable_time) { 00713 protocol_stack_interface_set_reachable_time(cur, reachable_time); 00714 } 00715 00716 retrans_timer = common_read_32_bit(dptr); 00717 dptr += 4; 00718 if (retrans_timer != 0) { 00719 cur->ipv6_neighbour_cache.retrans_timer = retrans_timer; 00720 } 00721 00722 const uint8_t *mtu_option = icmpv6_find_option_in_buffer(buf, 12, ICMPV6_OPT_MTU, 1); 00723 uint32_t mtu = mtu_option ? common_read_32_bit(mtu_option + 4) : 0; 00724 00725 sockaddr_t ll_addr = { .addr_type = ADDR_NONE }; 00726 const uint8_t *sllao = icmpv6_find_option_in_buffer(buf, 12, ICMPV6_OPT_SRC_LL_ADDR, 0); 00727 if (sllao) { 00728 if (cur->if_llao_parse(cur, sllao, &ll_addr)) { 00729 ncache_entry = ipv6_neighbour_update_unsolicited(&cur->ipv6_neighbour_cache, buf->src_sa .address , ll_addr.addr_type , ll_addr.address ); 00730 } 00731 } 00732 00733 buffer_data_strip_header(buf, 12); 00734 data_len -= 12; 00735 00736 if (cur->nwk_id == IF_6LoWPAN) { 00737 const uint8_t *abro; 00738 bool uptodate; 00739 00740 /* ABRO processing - aiming to separate this from standard processing; only 6LRs need to use ABROs */ 00741 abro = icmpv6_find_option_in_buffer(buf, 0, ICMPV6_OPT_AUTHORITATIVE_BORDER_RTR, 3); 00742 if (abro) { 00743 uptodate = nd_ra_process_abro(cur, buf, abro + 2, flags, router_lifetime); 00744 /* If ABRO processing indicated stale info, skip normal processing */ 00745 if (!uptodate) { 00746 goto drop; 00747 } 00748 #ifndef NO_RADV_TX 00749 if (hoplimit != 0) { 00750 cur->adv_cur_hop_limit = hoplimit; 00751 } 00752 if (reachable_time != 0) { 00753 cur->adv_reachable_time = reachable_time; 00754 } 00755 if (retrans_timer != 0) { 00756 cur->adv_retrans_timer = retrans_timer; 00757 } 00758 if (mtu != 0) { 00759 cur->adv_link_mtu = mtu; 00760 } 00761 #endif 00762 } 00763 } 00764 if (cur->recv_ra_routes) { 00765 if (router_lifetime) { 00766 tr_debug("Possible Default Router"); 00767 switch (flags & RA_PRF_MASK) { 00768 case RA_PRF_LOW: 00769 preference = -1; 00770 break; 00771 case RA_PRF_HIGH: 00772 preference = +1; 00773 break; 00774 default: 00775 preference = 0; 00776 break; // invalid is treated as 0 00777 } 00778 if (router_lifetime > longest_route_lifetime) { 00779 longest_route_lifetime = router_lifetime; 00780 } 00781 } 00782 ipv6_route_add(NULL, 0, cur->id, buf->src_sa .address , ROUTE_RADV, router_lifetime, preference); 00783 } 00784 00785 if (mtu >= IPV6_MIN_LINK_MTU && mtu <= cur->max_link_mtu) { 00786 cur->ipv6_neighbour_cache.link_mtu = mtu; 00787 } 00788 00789 //Scan All options 00790 while (data_len) { 00791 uint8_t type = *dptr++; 00792 uint16_t length = *dptr++ * 8; 00793 00794 if (type == ICMPV6_OPT_PREFIX_INFO && cur->recv_ra_prefixes && length == 32) { 00795 uint8_t *ptr = dptr; 00796 uint8_t prefix_length = *ptr++; 00797 uint8_t prefix_flags = *ptr++; 00798 00799 uint32_t valid_lifetime = common_read_32_bit(ptr); 00800 ptr += 4; 00801 uint32_t preferred_lifetime = common_read_32_bit(ptr); 00802 ptr += 8; //Update 32-bit time and reserved 32-bit 00803 const uint8_t *prefix_ptr = ptr; 00804 00805 //Check is L Flag active 00806 if (prefix_flags & PIO_L) { 00807 //define ONLink Route Information 00808 //tr_debug("Register On Link Prefix to routing table"); 00809 ipv6_route_add(prefix_ptr, prefix_length, cur->id, NULL, ROUTE_RADV, valid_lifetime, 0); 00810 } 00811 00812 //Check if A-Flag 00813 if (prefix_flags & PIO_A) { 00814 if (icmpv6_slaac_prefix_update(cur, prefix_ptr, prefix_length, valid_lifetime, preferred_lifetime) != 0) { 00815 ipv6_interface_slaac_handler(cur, prefix_ptr, prefix_length, valid_lifetime, preferred_lifetime); 00816 } 00817 00818 //tr_debug("Prefix: %s", trace_ipv6(prefix_ptr)); 00819 } 00820 00821 // If the R flag is set and we have SLLAO, let's add a neighbour cache entry. 00822 // This helps reduce RPL noise with source routing - may otherwise be good. 00823 // Note that existence of a neighbour cache entry doesn't affect routing - we 00824 // won't use it unless we otherwise decide they're on-link, eg from a source 00825 // routing header directing to them 00826 if ((prefix_flags & PIO_R) && ll_addr.addr_type != ADDR_NONE ) { 00827 ipv6_neighbour_update_unsolicited(&cur->ipv6_neighbour_cache, prefix_ptr, ll_addr.addr_type , ll_addr.address ); 00828 } 00829 } else if (type == ICMPV6_OPT_ROUTE_INFO && cur->recv_ra_routes) { 00830 uint8_t prefix_length = dptr[0]; 00831 uint8_t route_flags = dptr[1]; 00832 uint32_t route_lifetime = common_read_32_bit(dptr + 2); 00833 uint8_t *prefix_ptr = dptr + 6; 00834 // Check option is long enough for prefix 00835 if (length < 8 + (prefix_length + 7u) / 8) { 00836 goto next_option; 00837 } 00838 switch (route_flags & RA_PRF_MASK) { 00839 case RA_PRF_LOW: 00840 preference = -1; 00841 break; 00842 case RA_PRF_MEDIUM: 00843 preference = 0; 00844 break; 00845 case RA_PRF_HIGH: 00846 preference = +1; 00847 break; 00848 default: 00849 goto next_option; // invalid not accepted 00850 } 00851 if (route_lifetime > longest_route_lifetime) { 00852 longest_route_lifetime = route_lifetime; 00853 } 00854 00855 //Call route Update 00856 tr_info("Route: %s Lifetime: %lu Pref: %d", trace_ipv6_prefix(prefix_ptr, prefix_length), (unsigned long) route_lifetime, preference); 00857 if (route_lifetime) { 00858 ipv6_route_add(prefix_ptr, prefix_length, cur->id, buf->src_sa .address , ROUTE_RADV, route_lifetime, preference); 00859 } else { 00860 ipv6_route_delete(prefix_ptr, prefix_length, cur->id, buf->src_sa .address , ROUTE_RADV); 00861 } 00862 } else if (type == ICMPV6_OPT_6LOWPAN_CONTEXT) { 00863 nd_ra_process_lowpan_context_option(cur, dptr - 2); 00864 } 00865 next_option: 00866 //UPdate length and 00867 data_len -= length; 00868 dptr += length - 2; 00869 } 00870 00871 /* RFC 4861 says to always set IsRouter on receipt of any RA, but this 00872 * seems to make more sense - a shutting-down router (sending the final 00873 * MAX_FINAL_RTR_ADVERTISEMENTS), or a router advertising only prefixes 00874 * shouldn't really be marked as a router. So only set IsRouter if 00875 * a route was advertised (with non-0 lifetime). 00876 */ 00877 if (longest_route_lifetime) { 00878 if (!ncache_entry) { 00879 ncache_entry = ipv6_neighbour_lookup(&cur->ipv6_neighbour_cache, buf->src_sa .address ); 00880 } 00881 00882 if (ncache_entry) { 00883 ncache_entry->is_router = true; 00884 } 00885 } 00886 00887 drop: 00888 return buffer_free(buf); 00889 } 00890 00891 void icmpv6_recv_ra_routes(protocol_interface_info_entry_t *cur, bool enable) 00892 { 00893 if (cur->recv_ra_routes != enable) { 00894 cur->recv_ra_routes = enable; 00895 if (!enable) { 00896 ipv6_route_table_remove_info(cur->id, ROUTE_RADV, NULL); 00897 } 00898 } 00899 } 00900 00901 void icmpv6_recv_ra_prefixes(protocol_interface_info_entry_t *cur, bool enable) 00902 { 00903 if (cur->recv_ra_prefixes != enable) { 00904 cur->recv_ra_prefixes = enable; 00905 if (!enable) { 00906 addr_set_non_preferred(cur, ADDR_SOURCE_SLAAC); 00907 } 00908 } 00909 } 00910 00911 static buffer_t *icmpv6_redirect_handler(buffer_t *buf, protocol_interface_info_entry_t *cur) 00912 { 00913 const uint8_t *ptr = buffer_data_pointer(buf); 00914 const uint8_t *tgt = ptr + 4; 00915 const uint8_t *dest = ptr + 20; 00916 sockaddr_t tgt_ll = { .addr_type = ADDR_NONE }; 00917 00918 if (buf->options .hop_limit != 255) { 00919 goto drop; 00920 } 00921 00922 if (!addr_is_ipv6_link_local(buf->src_sa .address )) { 00923 goto drop; 00924 } 00925 00926 if (buf->options .code != 0) { 00927 goto drop; 00928 } 00929 00930 if (!icmpv6_options_well_formed_in_buffer(buf, 36)) { 00931 goto drop; 00932 } 00933 00934 if (addr_is_ipv6_multicast(dest)) { 00935 goto drop; 00936 } 00937 00938 const uint8_t *tllao = icmpv6_find_option_in_buffer(buf, 36, ICMPV6_OPT_TGT_LL_ADDR, 0); 00939 if (tllao) { 00940 cur->if_llao_parse(cur, tllao, &tgt_ll); 00941 } 00942 ipv6_destination_redirect(tgt, buf->src_sa .address , dest, buf->interface ->id, tgt_ll.addr_type , tgt_ll.address ); 00943 return buffer_free(buf); 00944 00945 drop: 00946 tr_warn("Redirect drop"); 00947 return buffer_free(buf); 00948 } 00949 00950 static buffer_t *icmpv6_na_handler(buffer_t *buf) 00951 { 00952 protocol_interface_info_entry_t *cur; 00953 uint8_t *dptr = buffer_data_pointer(buf); 00954 uint8_t flags; 00955 const uint8_t *target; 00956 const uint8_t *tllao; 00957 if_address_entry_t *addr_entry; 00958 ipv6_neighbour_t *neighbour_entry; 00959 00960 //"Parse NA at IPv6\n"); 00961 00962 if (buf->options .code != 0 || buf->options .hop_limit != 255) { 00963 goto drop; 00964 } 00965 00966 if (!icmpv6_options_well_formed_in_buffer(buf, 20)) { 00967 goto drop; 00968 } 00969 00970 // Skip the 4 reserved bytes 00971 flags = *dptr; 00972 dptr += 4; 00973 00974 // Note the target IPv6 address 00975 target = dptr; 00976 00977 if (addr_is_ipv6_multicast(target)) { 00978 goto drop; 00979 } 00980 00981 /* Solicited flag must be clear if sent to a multicast address */ 00982 if (addr_is_ipv6_multicast(buf->dst_sa .address ) && (flags & NA_S)) { 00983 goto drop; 00984 } 00985 00986 cur = buf->interface ; 00987 00988 /* RFC 4862 5.4.4 DAD checks */ 00989 addr_entry = addr_get_entry(cur, target); 00990 if (addr_entry) { 00991 if (addr_entry->tentative) { 00992 tr_debug("Received NA for our tentative address"); 00993 addr_duplicate_detected(cur, target); 00994 } else { 00995 tr_debug("NA received for our own address: %s", trace_ipv6(target)); 00996 } 00997 goto drop; 00998 } 00999 01000 const uint8_t *aro = icmpv6_find_option_in_buffer(buf, 20, ICMPV6_OPT_ADDR_REGISTRATION, 2); 01001 if (aro) { 01002 if (cur->ipv6_neighbour_cache.recv_na_aro) { 01003 icmpv6_na_aro_handler(cur, aro, buf->dst_sa .address ); 01004 } 01005 if (ws_info(cur)) { 01006 icmpv6_na_wisun_aro_handler(cur, aro, buf->src_sa .address ); 01007 } 01008 } 01009 01010 /* No need to create a neighbour cache entry if one doesn't already exist */ 01011 neighbour_entry = ipv6_neighbour_lookup(&cur->ipv6_neighbour_cache, target); 01012 if (!neighbour_entry) { 01013 goto drop; 01014 } 01015 01016 tllao = icmpv6_find_option_in_buffer(buf, 20, ICMPV6_OPT_TGT_LL_ADDR, 0); 01017 if (!tllao || !cur->if_llao_parse(cur, tllao, &buf->dst_sa )) { 01018 buf->dst_sa .addr_type = ADDR_NONE ; 01019 } 01020 01021 ipv6_neighbour_update_from_na(&cur->ipv6_neighbour_cache, neighbour_entry, flags, buf->dst_sa .addr_type , buf->dst_sa .address ); 01022 if (ws_info(cur) && neighbour_entry->state == IP_NEIGHBOUR_REACHABLE) { 01023 tr_debug("NA neigh update"); 01024 ws_common_neighbor_update(cur, target); 01025 } 01026 01027 drop: 01028 return buffer_free(buf); 01029 } 01030 #endif // HAVE_IPV6_ND 01031 01032 buffer_t *icmpv6_up(buffer_t *buf) 01033 { 01034 protocol_interface_info_entry_t *cur = NULL; 01035 uint8_t *dptr = buffer_data_pointer(buf); 01036 uint16_t data_len = buffer_data_length(buf); 01037 01038 cur = buf->interface ; 01039 01040 01041 01042 if (data_len < 4) { 01043 //tr_debug("Ic1"); 01044 goto drop; 01045 01046 } 01047 01048 buf->options .type = *dptr++; 01049 buf->options .code = *dptr++; 01050 01051 if (buf->options .ll_security_bypass_rx ) { 01052 if (!ws_info(buf->interface ) 01053 || (buf->options .type == ICMPV6_TYPE_INFO_RPL_CONTROL 01054 && (buf->options .code != ICMPV6_CODE_RPL_DIO 01055 && buf->options .code != ICMPV6_CODE_RPL_DIS))) { 01056 goto drop; 01057 } 01058 } 01059 01060 /* Check FCS first */ 01061 if (buffer_ipv6_fcf(buf, IPV6_NH_ICMPV6)) { 01062 tr_warn("ICMP cksum error!"); 01063 protocol_stats_update(STATS_IP_CKSUM_ERROR, 1); 01064 goto drop; 01065 } 01066 01067 //Skip ICMP Header Static 4 bytes length 01068 buffer_data_strip_header(buf, 4); 01069 01070 if (cur->if_icmp_handler) { 01071 bool bounce = false; 01072 buf = cur->if_icmp_handler(cur, buf, &bounce); 01073 if (!buf || bounce) { 01074 return buf; 01075 } 01076 } 01077 01078 switch (buf->options .type ) { 01079 #ifdef HAVE_IPV6_ND 01080 case ICMPV6_TYPE_INFO_RS: 01081 buf = icmpv6_rs_handler(buf, cur); 01082 break; 01083 01084 case ICMPV6_TYPE_INFO_RA: 01085 buf = icmpv6_ra_handler(buf); 01086 break; 01087 01088 case ICMPV6_TYPE_INFO_NS: 01089 buf = icmpv6_ns_handler(buf); 01090 break; 01091 01092 case ICMPV6_TYPE_INFO_NA: 01093 buf = icmpv6_na_handler(buf); 01094 break; 01095 01096 case ICMPV6_TYPE_INFO_REDIRECT: 01097 buf = icmpv6_redirect_handler(buf, cur); 01098 break; 01099 #endif 01100 01101 case ICMPV6_TYPE_INFO_ECHO_REQUEST: 01102 tr_debug("ICMP echo request from: %s", trace_ipv6(buf->src_sa .address )); 01103 buf = icmpv6_echo_request_handler(buf); 01104 break; 01105 01106 case ICMPV6_TYPE_INFO_ECHO_REPLY: 01107 ipv6_neighbour_reachability_confirmation(buf->src_sa .address , buf->interface ->id); 01108 /* fall through */ 01109 01110 case ICMPV6_TYPE_ERROR_DESTINATION_UNREACH: 01111 #ifdef HAVE_RPL_ROOT 01112 if (buf->options .type == ICMPV6_TYPE_ERROR_DESTINATION_UNREACH && buf->options .code == ICMPV6_CODE_DST_UNREACH_SRC_RTE_HDR_ERR) { 01113 buf = rpl_control_source_route_error_handler(buf, cur); 01114 } 01115 #endif 01116 /* fall through */ 01117 01118 default: 01119 if (buf) { 01120 buf->info = (buffer_info_t)(B_FROM_ICMP | B_TO_APP | B_DIR_UP); 01121 buf->options .type = (uint8_t) SOCKET_FAMILY_IPV6; 01122 buf->options .code = IPV6_NH_ICMPV6; 01123 buf->dst_sa .port = 0xffff; 01124 /* Put back ICMP header */ 01125 buffer_data_reserve_header(buf, 4); 01126 } 01127 break; 01128 01129 case ICMPV6_TYPE_INFO_MCAST_LIST_REPORT: 01130 buf = mld_report_handler(buf, cur); 01131 break; 01132 01133 case ICMPV6_TYPE_INFO_MCAST_LIST_QUERY: 01134 buf = mld_query_handler(buf, cur); 01135 break; 01136 01137 #ifndef NO_IPV6_PMTUD 01138 case ICMPV6_TYPE_ERROR_PACKET_TOO_BIG: 01139 buf = icmpv6_packet_too_big_handler(buf); 01140 break; 01141 #endif 01142 01143 #ifdef HAVE_RPL 01144 case ICMPV6_TYPE_INFO_RPL_CONTROL: 01145 buf = rpl_control_handler(buf); 01146 break; 01147 #endif 01148 01149 #ifdef HAVE_MPL 01150 case ICMPV6_TYPE_INFO_MPL_CONTROL: 01151 buf = mpl_control_handler(buf, cur); 01152 break; 01153 #endif 01154 01155 #ifdef HAVE_6LOWPAN_BORDER_ROUTER 01156 case ICMPV6_TYPE_INFO_DAR: 01157 01158 if (cur->nwk_id == IF_6LoWPAN) { 01159 if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { 01160 buf = nd_dar_parse(buf, cur); 01161 break; 01162 } 01163 } 01164 goto drop; 01165 #endif 01166 #ifdef HAVE_6LOWPAN_ROUTER 01167 case ICMPV6_TYPE_INFO_DAC: 01168 if (cur->nwk_id == IF_6LoWPAN) { 01169 if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY) { 01170 buf = nd_dac_handler(buf, cur); 01171 break; 01172 } 01173 } 01174 goto drop; 01175 #endif 01176 01177 } 01178 01179 return buf; 01180 01181 drop: 01182 return buffer_free(buf); 01183 } 01184 01185 buffer_t *icmpv6_down(buffer_t *buf) 01186 { 01187 protocol_interface_info_entry_t *cur = buf->interface ; 01188 01189 buf = buffer_headroom(buf, 4); 01190 if (buf) { 01191 uint8_t *dptr; 01192 dptr = buffer_data_reserve_header(buf, 4); 01193 buf->info = (buffer_info_t)(B_FROM_ICMP | B_TO_IPV6 | B_DIR_DOWN); 01194 01195 if (buf->src_sa .addr_type != ADDR_IPV6 ) { 01196 if (addr_interface_select_source(cur, buf->src_sa .address , buf->dst_sa .address , 0) != 0) { 01197 tr_err("ICMP:InterFace Address Get Fail--> free Buffer"); 01198 return buffer_free(buf); 01199 } else { 01200 buf->src_sa .addr_type = ADDR_IPV6 ; 01201 } 01202 01203 } 01204 01205 *dptr++ = buf->options .type ; 01206 *dptr++ = buf->options .code ; 01207 common_write_16_bit(0, dptr); 01208 common_write_16_bit(buffer_ipv6_fcf(buf, IPV6_NH_ICMPV6), dptr); 01209 buf->options .type = IPV6_NH_ICMPV6; 01210 buf->options .code = 0; 01211 buf->options .traffic_class &= ~IP_TCLASS_ECN_MASK; 01212 } 01213 return (buf); 01214 } 01215 01216 #ifdef HAVE_IPV6_ND 01217 buffer_t *icmpv6_build_rs(protocol_interface_info_entry_t *cur, const uint8_t *dest) 01218 { 01219 01220 buffer_t *buf = buffer_get(127); 01221 if (!buf) { 01222 return NULL; 01223 } 01224 01225 const uint8_t *src_address; 01226 uint8_t *ptr = buffer_data_pointer(buf); 01227 01228 memcpy(buf->dst_sa .address , dest ? dest : ADDR_LINK_LOCAL_ALL_ROUTERS, 16); 01229 buf->dst_sa .addr_type = ADDR_IPV6 ; 01230 01231 //select Address by Interface pointer and destination 01232 src_address = addr_select_source(cur, buf->dst_sa .address , 0); 01233 if (!src_address) { 01234 tr_debug("No source address defined"); 01235 return buffer_free(buf); 01236 } 01237 01238 memcpy(buf->src_sa .address , src_address, 16); 01239 buf->src_sa .addr_type = ADDR_IPV6 ; 01240 01241 buf->options .type = ICMPV6_TYPE_INFO_RS; 01242 buf->options .code = 0; 01243 buf->options .hop_limit = 255; 01244 ptr = common_write_32_bit(0, ptr); 01245 01246 /* RFC 6775 mandates SLLAO in RS */ 01247 ptr = icmpv6_write_icmp_lla(cur, ptr, ICMPV6_OPT_SRC_LL_ADDR, true, src_address); 01248 01249 buf->buf_end = ptr - buf->buf ; 01250 buf->interface = cur; 01251 buf->info = (buffer_info_t)(B_FROM_ICMP | B_TO_ICMP | B_DIR_DOWN); 01252 01253 return buf; 01254 } 01255 01256 uint8_t *icmpv6_write_icmp_lla(protocol_interface_info_entry_t *cur, uint8_t *dptr, uint8_t icmp_opt, bool must, const uint8_t *ip_addr) 01257 { 01258 dptr += cur->if_llao_write(cur, dptr, icmp_opt, must, ip_addr); 01259 01260 return dptr; 01261 } 01262 01263 /* 01264 * Write either an ICMPv6 Prefix Information Option for a Router Advertisement 01265 * (RFC4861+6275), or an RPL Prefix Information Option (RFC6550). 01266 * Same payload, different type/len. 01267 */ 01268 uint8_t *icmpv6_write_prefix_option(const prefix_list_t *prefixes, uint8_t *dptr, uint8_t rpl_prefix, protocol_interface_info_entry_t *cur) 01269 { 01270 uint8_t flags; 01271 01272 ns_list_foreach(prefix_entry_t, prefix_ptr, prefixes) { 01273 flags = prefix_ptr->options; 01274 if (prefix_ptr->prefix_len == 64) { 01275 /* XXX this seems dubious - shouldn't get_address_with_prefix be called every time? What if the address changes or is deleted? */ 01276 if (prefix_ptr->options & PIO_R) { 01277 const uint8_t *addr = addr_select_with_prefix(cur, prefix_ptr->prefix, prefix_ptr->prefix_len, 0); 01278 if (addr) { 01279 memcpy(prefix_ptr->prefix, addr, 16); 01280 } else { 01281 flags &= ~PIO_R; 01282 } 01283 } 01284 } 01285 if (rpl_prefix) { 01286 *dptr++ = RPL_PREFIX_INFO_OPTION; 01287 *dptr++ = 30; // Length in bytes, excluding these 2 01288 } else { 01289 *dptr++ = ICMPV6_OPT_PREFIX_INFO; 01290 *dptr++ = 4; // Length in 8-byte units 01291 } 01292 01293 *dptr++ = prefix_ptr->prefix_len; //length 01294 *dptr++ = flags; //Flags 01295 dptr = common_write_32_bit(prefix_ptr->lifetime, dptr); 01296 dptr = common_write_32_bit(prefix_ptr->preftime, dptr); 01297 dptr = common_write_32_bit(0, dptr); // Reserved2 01298 memcpy(dptr, prefix_ptr->prefix, 16); 01299 dptr += 16; 01300 } 01301 return dptr; 01302 } 01303 01304 /* 0 1 2 3 01305 * 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 01306 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 01307 * | Type | Length | Reserved | 01308 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 01309 * | MTU | 01310 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 01311 */ 01312 uint8_t *icmpv6_write_mtu_option(uint32_t mtu, uint8_t *dptr) 01313 { 01314 *dptr++ = ICMPV6_OPT_MTU; 01315 *dptr++ = 1; // length 01316 dptr = common_write_16_bit(0, dptr); 01317 dptr = common_write_32_bit(mtu, dptr); 01318 return dptr; 01319 } 01320 01321 void ack_receive_cb(struct buffer *buffer_ptr, uint8_t status) 01322 { 01323 /*icmpv6_na_handler functionality based on ACK*/ 01324 ipv6_neighbour_t *neighbour_entry; 01325 uint8_t ll_target[16]; 01326 01327 if (status != SOCKET_TX_DONE) { 01328 /*NS failed*/ 01329 return; 01330 } 01331 01332 if (buffer_ptr->dst_sa .addr_type == ADDR_IPV6 ) { 01333 /*Full IPv6 address*/ 01334 memcpy(ll_target, buffer_ptr->dst_sa .address , 16); 01335 } else if (buffer_ptr->dst_sa .addr_type == ADDR_802_15_4_LONG ) { 01336 // Build link local address from long MAC address 01337 memcpy(ll_target, ADDR_LINK_LOCAL_PREFIX, 8); 01338 memcpy(ll_target + 8, &buffer_ptr->dst_sa .address [2], 8); 01339 ll_target[8] ^= 2; 01340 } else { 01341 tr_warn("wrong address %d %s", buffer_ptr->dst_sa .addr_type , trace_array(buffer_ptr->dst_sa .address , 16)); 01342 return; 01343 } 01344 01345 neighbour_entry = ipv6_neighbour_lookup(&buffer_ptr->interface ->ipv6_neighbour_cache, ll_target); 01346 if (neighbour_entry) { 01347 ipv6_neighbour_update_from_na(&buffer_ptr->interface ->ipv6_neighbour_cache, neighbour_entry, NA_S, buffer_ptr->dst_sa .addr_type , buffer_ptr->dst_sa .address ); 01348 } 01349 01350 if (ws_info(buffer_ptr->interface )) { 01351 ws_common_neighbor_update(buffer_ptr->interface , ll_target); 01352 } 01353 } 01354 void ack_remove_neighbour_cb(struct buffer *buffer_ptr, uint8_t status) 01355 { 01356 /*icmpv6_na_handler functionality based on ACK*/ 01357 uint8_t ll_target[16]; 01358 (void)status; 01359 01360 if (buffer_ptr->dst_sa .addr_type == ADDR_IPV6 ) { 01361 /*Full IPv6 address*/ 01362 memcpy(ll_target, buffer_ptr->dst_sa .address , 16); 01363 } else if (buffer_ptr->dst_sa .addr_type == ADDR_802_15_4_LONG ) { 01364 // Build link local address from long MAC address 01365 memcpy(ll_target, ADDR_LINK_LOCAL_PREFIX, 8); 01366 memcpy(ll_target + 8, &buffer_ptr->dst_sa .address [2], 8); 01367 ll_target[8] ^= 2; 01368 } else { 01369 tr_warn("wrong address %d %s", buffer_ptr->dst_sa .addr_type , trace_array(buffer_ptr->dst_sa .address , 16)); 01370 return; 01371 } 01372 if (ws_info(buffer_ptr->interface )) { 01373 ws_common_neighbor_remove(buffer_ptr->interface , ll_target); 01374 } 01375 01376 } 01377 01378 static void icmpv6_aro_cb(buffer_t *buf, uint8_t status) 01379 { 01380 uint8_t ll_address[16]; 01381 if (buf->dst_sa .addr_type == ADDR_IPV6 ) { 01382 /*Full IPv6 address*/ 01383 memcpy(ll_address, buf->dst_sa .address , 16); 01384 } else if (buf->dst_sa .addr_type == ADDR_802_15_4_LONG ) { 01385 // Build link local address from long MAC address 01386 memcpy(ll_address, ADDR_LINK_LOCAL_PREFIX, 8); 01387 memcpy(ll_address + 8, &buf->dst_sa .address [2], 8); 01388 ll_address[8] ^= 2; 01389 } 01390 rpl_control_address_register_done(buf->interface , ll_address, status); 01391 if (status != SOCKET_TX_DONE) { 01392 ws_common_aro_failure(buf->interface , ll_address, false); 01393 } 01394 } 01395 01396 buffer_t *icmpv6_build_ns(protocol_interface_info_entry_t *cur, const uint8_t target_addr[16], const uint8_t *prompting_src_addr, bool unicast, bool unspecified_source, const aro_t *aro) 01397 { 01398 if (!cur || addr_is_ipv6_multicast(target_addr)) { 01399 return NULL; 01400 } 01401 01402 buffer_t *buf = buffer_get(127); 01403 if (!buf) { 01404 return buf; 01405 } 01406 01407 buf->options .type = ICMPV6_TYPE_INFO_NS; 01408 buf->options .code = 0; 01409 buf->options .hop_limit = 255; 01410 01411 uint8_t *ptr = buffer_data_pointer(buf); 01412 ptr = common_write_32_bit(0, ptr); 01413 memcpy(ptr, target_addr, 16); 01414 ptr += 16; 01415 01416 if (aro) { 01417 *ptr++ = ICMPV6_OPT_ADDR_REGISTRATION; 01418 *ptr++ = 2; 01419 *ptr++ = aro->status; /* Should be ARO_SUCCESS in an NS */ 01420 *ptr++ = 0; 01421 ptr = common_write_16_bit(0, ptr); 01422 ptr = common_write_16_bit(aro->lifetime, ptr); 01423 memcpy(ptr, aro->eui64, 8); 01424 ptr += 8; 01425 } 01426 01427 if (unicast) { 01428 memcpy(buf->dst_sa .address , target_addr, 16); 01429 } else { 01430 memcpy(buf->dst_sa .address , ADDR_MULTICAST_SOLICITED, 13); 01431 memcpy(buf->dst_sa .address + 13, target_addr + 13, 3); 01432 } 01433 buf->dst_sa .addr_type = ADDR_IPV6 ; 01434 01435 if (unspecified_source) { 01436 memset(buf->src_sa .address , 0, 16); 01437 } else { 01438 /* RFC 4861 7.2.2. says we should use the source of traffic prompting the NS, if possible */ 01439 /* This is also used to specify the address for ARO messages */ 01440 if (aro || (prompting_src_addr && addr_is_assigned_to_interface(cur, prompting_src_addr))) { 01441 memcpy(buf->src_sa .address , prompting_src_addr, 16); 01442 } else { 01443 /* Otherwise, according to RFC 4861, we could use any address. 01444 * But there is a 6LoWPAN/RPL hiccup - a node may have registered 01445 * to us with an ARO, and we might send it's global address a NUD 01446 * probe. But it doesn't know _our_ global address, which default 01447 * address selection would favour. 01448 * If it was still a host, we'd get away with using our global 01449 * address, as we'd be its default route, so its reply comes to us. 01450 * But if it's switched to being a RPL router, it would send its 01451 * globally-addressed reply packet up the RPL DODAG. 01452 * Avoid the problem by using link-local source. 01453 * This will still leave us with an asymmetrical connection - its 01454 * global address on-link for us, and we send to it directly (and 01455 * can NUD probe it), whereas it regards us as off-link and will 01456 * go via RPL (and won't probe us). But it will work fine. 01457 */ 01458 if (addr_interface_get_ll_address(cur, buf->src_sa .address , 0) < 0) { 01459 tr_debug("No address for NS"); 01460 return buffer_free(buf); 01461 } 01462 } 01463 /* SLLAO is required if we're sending an ARO */ 01464 /* This rule can be bypassed with flag use_eui64_as_slla_in_aro */ 01465 if (!cur->ipv6_neighbour_cache.use_eui64_as_slla_in_aro) { 01466 ptr = icmpv6_write_icmp_lla(cur, ptr, ICMPV6_OPT_SRC_LL_ADDR, aro, buf->src_sa .address ); 01467 } 01468 /* If ARO Success sending is omitted, MAC ACK is used instead */ 01469 /* Setting callback for receiving ACK from adaptation layer */ 01470 if (aro && cur->ipv6_neighbour_cache.omit_na_aro_success) { 01471 buf->ack_receive_cb = icmpv6_aro_cb; 01472 } 01473 } 01474 if (unicast && (!aro && cur->ipv6_neighbour_cache.omit_na)) { 01475 /*MAC ACK is processed as success response*/ 01476 buf->ack_receive_cb = ack_receive_cb; 01477 } 01478 01479 buf->src_sa .addr_type = ADDR_IPV6 ; 01480 01481 /* NS packets are implicitly on-link. If we ever find ourselves sending an 01482 * NS to a global address, it's because we are in some way regarding 01483 * it as on-link. (eg, redirect, RPL source routing header). We force 01484 * transmission as on-link here, regardless of routing table, to avoid any 01485 * potential oddities. 01486 */ 01487 ipv6_buffer_route_to(buf, buf->dst_sa .address , cur); 01488 01489 buffer_data_end_set(buf, ptr); 01490 buf->interface = cur; 01491 buf->info = (buffer_info_t)(B_FROM_ICMP | B_TO_ICMP | B_DIR_DOWN); 01492 01493 return buf; 01494 } 01495 #endif // HAVE_IPV6_ND 01496 01497 void icmpv6_build_echo_req(protocol_interface_info_entry_t *cur, const uint8_t target_addr[16]) 01498 { 01499 const uint8_t *src; 01500 buffer_t *buf = buffer_get(127); 01501 if (!buf) { 01502 return; 01503 } 01504 01505 buf->options .type = ICMPV6_TYPE_INFO_ECHO_REQUEST; 01506 buf->options .code = 0; 01507 buf->options .hop_limit = 255; 01508 01509 uint8_t *ptr = buffer_data_pointer(buf); 01510 memcpy(ptr, target_addr, 16); 01511 ptr += 16; 01512 01513 memcpy(buf->dst_sa .address , target_addr, 16); 01514 buf->dst_sa .addr_type = ADDR_IPV6 ; 01515 //Select Address By Destination 01516 src = addr_select_source(cur, buf->dst_sa .address , 0); 01517 if (src) { 01518 memcpy(buf->src_sa .address , src, 16); 01519 } else { 01520 tr_debug("No address for NS"); 01521 buffer_free(buf); 01522 return; 01523 } 01524 buf->src_sa .addr_type = ADDR_IPV6 ; 01525 buffer_data_end_set(buf, ptr); 01526 buf->interface = cur; 01527 buf->info = (buffer_info_t)(B_FROM_ICMP | B_TO_ICMP | B_DIR_DOWN); 01528 protocol_push(buf); 01529 } 01530 01531 #ifdef HAVE_6LOWPAN_ROUTER 01532 buffer_t *icmpv6_build_dad(protocol_interface_info_entry_t *cur, buffer_t *buf, uint8_t type, const uint8_t dest_addr[16], const uint8_t eui64[8], const uint8_t reg_addr[16], uint8_t status, uint16_t lifetime) 01533 { 01534 if (!cur) { 01535 return NULL; 01536 } 01537 01538 if (!buf) { 01539 buf = buffer_get(4 + 8 + 16); 01540 if (!buf) { 01541 return buf; 01542 } 01543 } 01544 01545 uint8_t *ptr = buffer_data_pointer(buf); 01546 buf->options .type = type; 01547 buf->options .code = 0; 01548 buf->options .hop_limit = 64; /* RFC 6775 MULTIHOP_HOPLIMIT */ 01549 01550 *ptr++ = status; 01551 *ptr++ = 0; 01552 ptr = common_write_16_bit(lifetime, ptr); 01553 memcpy(ptr, eui64, 8); 01554 ptr += 8; 01555 memcpy(ptr, reg_addr, 16); 01556 ptr += 16; 01557 buffer_data_end_set(buf, ptr); 01558 01559 memcpy(buf->dst_sa .address , dest_addr, 16); 01560 buf->dst_sa .addr_type = ADDR_IPV6 ; 01561 01562 const uint8_t *src = addr_select_source(cur, buf->dst_sa .address , 0); 01563 if (src && !addr_is_ipv6_link_local(src)) { 01564 memcpy(buf->src_sa .address , src, 16); 01565 } else { 01566 tr_debug("No address for DAD"); 01567 return buffer_free(buf); 01568 } 01569 buf->src_sa .addr_type = ADDR_IPV6 ; 01570 buf->interface = cur; 01571 buf->info = (buffer_info_t)(B_FROM_ICMP | B_TO_ICMP | B_DIR_DOWN); 01572 01573 return buf; 01574 } 01575 #endif // HAVE_6LOWPAN_ROUTER 01576 01577 #ifdef HAVE_IPV6_ND 01578 /* 01579 * Neighbor Advertisement Message Format 01580 * 01581 * 0 1 2 3 01582 * 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 01583 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 01584 * | Type | Code | Checksum | 01585 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 01586 * |R|S|O| Reserved | 01587 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 01588 * | | 01589 * + + 01590 * | | 01591 * + Target Address + 01592 * | | 01593 * + + 01594 * | | 01595 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 01596 * | Options ... 01597 * +-+-+-+-+-+-+-+-+-+-+-+- 01598 * 01599 * R Router flag. 01600 * S Solicited flag. 01601 * O Override flag. 01602 */ 01603 01604 buffer_t *icmpv6_build_na(protocol_interface_info_entry_t *cur, bool solicited, bool override, bool tllao_required, const uint8_t target[static 16], const aro_t *aro, const uint8_t src_addr[static 16]) 01605 { 01606 uint8_t *ptr; 01607 uint8_t flags; 01608 01609 /* Check if ARO response and status == success, then sending can be omitted with flag */ 01610 if (aro && cur->ipv6_neighbour_cache.omit_na_aro_success && aro->status == ARO_SUCCESS) { 01611 tr_debug("Omit NA ARO success"); 01612 return NULL; 01613 } 01614 /* All other than ARO NA messages are omitted and MAC ACK is considered as success */ 01615 if (!tllao_required && (!aro && cur->ipv6_neighbour_cache.omit_na)) { 01616 return NULL; 01617 } 01618 01619 01620 buffer_t *buf = buffer_get(8 + 16 + 16 + 16); /* fixed, target addr, target ll addr, aro */ 01621 if (!buf) { 01622 return NULL; 01623 } 01624 01625 ptr = buffer_data_pointer(buf); 01626 buf->options .hop_limit = 255; 01627 01628 // Set the ICMPv6 NA type and code fields as per RFC4861 01629 buf->options .type = ICMPV6_TYPE_INFO_NA; 01630 buf->options .code = 0x00; 01631 01632 // If we're sending RAs, then we have to set the Router bit here 01633 // (RFC 4861 makes host trigger action when they see the IsRouter flag 01634 // go from true to false - RAs from us imply "IsRouter", apparently even if 01635 // Router Lifetime is 0. So keep R set as long as we're sending RAs) 01636 flags = icmpv6_radv_is_enabled(cur) ? NA_R : 0; 01637 01638 if (override) { 01639 flags |= NA_O; 01640 } 01641 01642 if (addr_is_ipv6_unspecified(src_addr)) { 01643 // Solicited flag must be 0 if responding to DAD 01644 memcpy(buf->dst_sa .address , ADDR_LINK_LOCAL_ALL_NODES, 16); 01645 } else { 01646 if (solicited) { 01647 flags |= NA_S; 01648 } 01649 01650 /* See RFC 6775 6.5.2 - errors are sent to LL64 address 01651 * derived from EUI-64, success to IP source address */ 01652 if (aro && aro->status != ARO_SUCCESS) { 01653 memcpy(buf->dst_sa .address , ADDR_LINK_LOCAL_PREFIX, 8); 01654 memcpy(buf->dst_sa .address + 8, aro->eui64, 8); 01655 buf->dst_sa .address [8] ^= 2; 01656 } else { 01657 memcpy(buf->dst_sa .address , src_addr, 16); 01658 } 01659 } 01660 buf->dst_sa .addr_type = ADDR_IPV6 ; 01661 01662 /* In theory we could just use addr_select_source(), as RFC 4861 allows 01663 * any address assigned to the interface as source. But RFC 6775 shows LL64 01664 * as the source in its appendix, sending NA to a global address, and our 01665 * lower layers go a bit funny with RPL during bootstrap if we send from a 01666 * global address to a global address. By favouring the target address as 01667 * source, we catch that 6LoWPAN case (the target is LL), as well as making 01668 * it look neater anyway. 01669 */ 01670 if (addr_is_assigned_to_interface(cur, target)) { 01671 memcpy(buf->src_sa .address , target, 16); 01672 } else { 01673 const uint8_t *src = addr_select_source(cur, buf->dst_sa .address , 0); 01674 if (!src) { 01675 tr_debug("No address"); 01676 return buffer_free(buf); 01677 } 01678 memcpy(buf->src_sa .address , src, 16); 01679 } 01680 buf->src_sa .addr_type = ADDR_IPV6 ; 01681 01682 ptr = common_write_32_bit((uint32_t) flags << 24, ptr); 01683 // Set the target IPv6 address 01684 memcpy(ptr, target, 16); 01685 ptr += 16; 01686 01687 // Set the target Link-Layer address 01688 ptr = icmpv6_write_icmp_lla(cur, ptr, ICMPV6_OPT_TGT_LL_ADDR, tllao_required, target); 01689 01690 if (aro) { 01691 *ptr++ = ICMPV6_OPT_ADDR_REGISTRATION; 01692 *ptr++ = 2; 01693 *ptr++ = aro->status; 01694 *ptr++ = 0; 01695 ptr = common_write_16_bit(0, ptr); 01696 ptr = common_write_16_bit(aro->lifetime, ptr); 01697 memcpy(ptr, aro->eui64, 8); 01698 ptr += 8; 01699 } 01700 if (ws_info(cur) && aro && aro->status != ARO_SUCCESS) { 01701 /*If Aro failed we will kill the neigbour after we have succeeded in sending message*/ 01702 if (!ws_common_negative_aro_mark(cur, aro->eui64)) { 01703 tr_debug("Neighbour removed for negative response send"); 01704 return buffer_free(buf); 01705 } 01706 buf->ack_receive_cb = ack_remove_neighbour_cb; 01707 } 01708 01709 //Force Next Hop is destination 01710 ipv6_buffer_route_to(buf, buf->dst_sa .address , cur); 01711 01712 buffer_data_end_set(buf, ptr); 01713 buf->info = (buffer_info_t)(B_DIR_DOWN | B_FROM_ICMP | B_TO_ICMP); 01714 buf->interface = cur; 01715 01716 tr_debug("Build NA"); 01717 01718 return (buf); 01719 } 01720 01721 #endif // HAVE_IPV6_ND 01722 01723 #ifdef HAVE_IPV6_ND 01724 /* Check whether the options section of an ICMPv6 message is well-formed */ 01725 bool icmpv6_options_well_formed(const uint8_t *dptr, uint_fast16_t dlen) 01726 { 01727 if (dlen % 8) { 01728 return false; 01729 } 01730 01731 while (dlen) { 01732 uint_fast16_t opt_len = dptr[1] * 8; 01733 if (opt_len == 0 || opt_len > dlen) { 01734 return false; 01735 } 01736 dptr += opt_len; 01737 dlen -= opt_len; 01738 } 01739 01740 return true; 01741 } 01742 01743 bool icmpv6_options_well_formed_in_buffer(const buffer_t *buf, uint16_t offset) 01744 { 01745 if (buffer_data_length(buf) < offset) { 01746 return false; 01747 } 01748 01749 return icmpv6_options_well_formed(buffer_data_pointer(buf) + offset, 01750 buffer_data_length(buf) - offset); 01751 } 01752 01753 /* 01754 * Search for the first option of the specified type (and optionally length). 01755 * Caller must have already checked the options are well-formed. 01756 * If optlen is non-zero, then options with different lengths are ignored. 01757 * Note that optlen is in 8-octet units. 01758 */ 01759 const uint8_t *icmpv6_find_option(const uint8_t *dptr, uint_fast16_t dlen, uint8_t option, uint8_t optlen) 01760 { 01761 while (dlen) { 01762 uint8_t type = dptr[0]; 01763 uint8_t len = dptr[1]; 01764 01765 if (type == option && (optlen == 0 || optlen == len)) { 01766 return dptr; 01767 } else { 01768 dptr += len * 8; 01769 dlen -= len * 8; 01770 } 01771 } 01772 return NULL; 01773 01774 } 01775 01776 const uint8_t *icmpv6_find_option_in_buffer(const buffer_t *buf, uint_fast16_t offset, uint8_t option, uint8_t optlen) 01777 { 01778 return icmpv6_find_option(buffer_data_pointer(buf) + offset, 01779 buffer_data_length(buf) - offset, option, optlen); 01780 } 01781 #endif // HAVE_IPV6_ND
Generated on Tue Jul 12 2022 13:54:24 by
