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.
icmpv6.c
00001 /* 00002 * Copyright (c) 2013-2018, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 #include "nsconfig.h" 00018 #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/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 ipv6_ptr = addr_select_source(cur, buf->dst_sa .address , 0); 00329 if (!ipv6_ptr) { 00330 tr_debug("No address"); 00331 return buffer_free(buf); 00332 } 00333 memcpy(buf->dst_sa .address , buf->src_sa .address , 16); 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 static void icmpv6_na_aro_handler(protocol_interface_info_entry_t *cur_interface, const uint8_t *dptr, const uint8_t *dst_addr) 00344 { 00345 (void)dst_addr; 00346 dptr += 2; 00347 uint16_t life_time; 00348 uint8_t nd_status = *dptr; 00349 dptr += 4; 00350 life_time = common_read_16_bit(dptr); 00351 dptr += 2; 00352 if (memcmp(dptr, cur_interface->mac, 8) != 0) { 00353 return; 00354 } 00355 00356 /* Failure responses go to LL64, and they thus don't actually indicate the 00357 * address that we were trying to register. So we have to rely on having 00358 * "current DAD address" stored. We don't get it from the packet in any case. 00359 */ 00360 if (!cur_interface->if_6lowpan_dad_process.active) { 00361 return; 00362 } 00363 00364 if_address_entry_t *addr_entry = addr_get_entry(cur_interface, cur_interface->if_6lowpan_dad_process.address); 00365 if (!addr_entry) { 00366 return; 00367 } 00368 00369 switch (nd_status) { 00370 case ARO_SUCCESS: 00371 addr_cb(cur_interface, addr_entry, ADDR_CALLBACK_DAD_COMPLETE); 00372 if (addr_entry->cb) { 00373 /* Lifetime is in minutes, state_timer in 1/10 s: a factor of 600 */ 00374 /* Set renewal to 75-85% of full lifetime by multiplying by [450..510] */ 00375 addr_entry->state_timer = life_time * randLIB_get_random_in_range(450, 510); 00376 } 00377 00378 break; 00379 00380 case ARO_DUPLICATE: 00381 addr_duplicate_detected(cur_interface, addr_entry->address); 00382 break; 00383 00384 case ARO_FULL: 00385 addr_cb(cur_interface, addr_entry, ADDR_CALLBACK_PARENT_FULL); 00386 break; 00387 } 00388 } 00389 00390 /* 00391 * Neighbor Solicitation Message Format 00392 * 00393 * 0 1 2 3 00394 * 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 00395 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00396 * | Type | Code | Checksum | 00397 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00398 * | Reserved | 00399 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00400 * | | 00401 * + + 00402 * | | 00403 * + Target Address + 00404 * | | 00405 * + + 00406 * | | 00407 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00408 * | Options ... 00409 * +-+-+-+-+-+-+-+-+-+-+-+- 00410 * 00411 * 00412 * Source/Target Link-layer Address 00413 * 00414 * 0 1 2 3 00415 * 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 00416 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00417 * | Type | Length | Link-Layer Address ... 00418 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00419 * 00420 */ 00421 static buffer_t *icmpv6_ns_handler(buffer_t *buf) 00422 { 00423 protocol_interface_info_entry_t *cur; 00424 uint8_t target[16]; 00425 uint8_t dummy_sllao[16]; 00426 bool proxy = false; 00427 const uint8_t *sllao; 00428 const uint8_t *aro; 00429 uint8_t *dptr = buffer_data_pointer(buf); 00430 aro_t aro_out = { .present = false }; 00431 00432 cur = buf->interface ; 00433 00434 if (buf->options .code != 0 || buf->options .hop_limit != 255) { 00435 goto drop; 00436 } 00437 00438 if (!icmpv6_options_well_formed_in_buffer(buf, 20)) { 00439 goto drop; 00440 } 00441 00442 sllao = icmpv6_find_option_in_buffer(buf, 20, ICMPV6_OPT_SRC_LL_ADDR, 0); 00443 00444 /* If no SLLAO, ignore ARO (RFC 6775 6.5) */ 00445 /* This rule can be bypassed by setting flag "use_eui64_as_slla_in_aro" to true */ 00446 if (cur->ipv6_neighbour_cache.recv_addr_reg && 00447 (cur->ipv6_neighbour_cache.use_eui64_as_slla_in_aro || sllao)) { 00448 aro = icmpv6_find_option_in_buffer(buf, 20, ICMPV6_OPT_ADDR_REGISTRATION, 0); 00449 } else { 00450 aro = NULL; 00451 } 00452 00453 /* ARO's length must be 2 and status must be 0 */ 00454 if (aro && (aro[1] != 2 || aro[2] != 0)) { 00455 goto drop; 00456 } 00457 00458 /* If there was no SLLAO on ARO, use mac address to create dummy one... */ 00459 if (aro && !sllao && cur->ipv6_neighbour_cache.use_eui64_as_slla_in_aro) { 00460 dummy_sllao[0] = ICMPV6_OPT_SRC_LL_ADDR; // Type 00461 dummy_sllao[1] = 2; // Length = 2x8 bytes 00462 memcpy(dummy_sllao + 2, aro + 8, 8); // EUI-64 00463 memset(dummy_sllao + 10, 0, 6); // Padding 00464 00465 sllao = dummy_sllao; 00466 } 00467 // Skip the 4 reserved bytes 00468 dptr += 4; 00469 00470 // Copy the target IPv6 address 00471 memcpy(target, dptr, 16); 00472 dptr += 16; 00473 00474 if (addr_is_ipv6_multicast(target)) { 00475 goto drop; 00476 } 00477 00478 if (addr_is_ipv6_unspecified(buf->src_sa .address )) { 00479 /* Dest must be to solicited-node multicast, without source LL-addr */ 00480 if (sllao || memcmp(buf->dst_sa .address , ADDR_MULTICAST_SOLICITED, 13) != 0) { 00481 goto drop; 00482 } 00483 00484 /* If unspecified source, ignore ARO (RFC 6775 6.5) */ 00485 aro = NULL; 00486 } 00487 00488 /* See RFC 4862 5.4.3 - hook for Duplicate Address Detection */ 00489 if (addr_is_tentative_for_interface(cur, target)) { 00490 if (addr_is_ipv6_unspecified(buf->src_sa .address )) { 00491 tr_debug("Received DAD NS for our tentative address"); 00492 /* Someone else is performing DAD */ 00493 addr_duplicate_detected(cur, target); 00494 } 00495 goto drop; 00496 } 00497 00498 /* This first check's a bit dodgy - it responds to our address on the other 00499 * interface, which we should only do in the whiteboard case. 00500 */ 00501 if (addr_interface_address_compare(cur, target) != 0) { 00502 //tr_debug("Received NS for proxy %s", trace_ipv6(target)); 00503 00504 proxy = true; 00505 //Filter Link Local scope 00506 if (addr_is_ipv6_link_local(target)) { 00507 goto drop; 00508 } 00509 00510 if (!nd_proxy_enabled_for_downstream(cur->id) || !nd_proxy_target_address_validation(cur->id, target)) { 00511 goto drop; 00512 } 00513 } 00514 00515 if (aro) { 00516 /* If it had an ARO, and we're paying attention to it, possibilities: 00517 * 1) No reply to NS now, we need to contact border router (false return) 00518 * 2) Reply to NS now, with ARO (true return, aro_out.present true) 00519 * 3) Reply to NS now, without ARO (true return, aro_out.present false) 00520 */ 00521 if (!nd_ns_aro_handler(cur, aro, sllao, buf->src_sa .address , &aro_out)) { 00522 goto drop; 00523 } 00524 } 00525 00526 /* If we're returning an ARO, then we assume the ARO handler has done the 00527 * necessary to the Neighbour Cache. Otherwise, normal RFC 4861 processing. */ 00528 if (!aro_out.present && 00529 sllao && cur->if_llao_parse(cur, sllao, &buf->dst_sa )) { 00530 ipv6_neighbour_update_unsolicited(&cur->ipv6_neighbour_cache, buf->src_sa .address , buf->dst_sa .addr_type , buf->dst_sa .address ); 00531 } 00532 00533 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 ); 00534 00535 buffer_free(buf); 00536 00537 return na_buf; 00538 00539 drop: 00540 buf = buffer_free(buf); 00541 00542 return buf; 00543 00544 } 00545 00546 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) 00547 { 00548 int ret_val = -1; 00549 00550 //Validate first current list If prefix is already defined adress 00551 ns_list_foreach_safe(if_address_entry_t, e, &cur->ip_addresses) { 00552 if (e->source == ADDR_SOURCE_SLAAC && (e->prefix_len == prefix_len) && bitsequal(e->address, prefix_ptr, prefix_len)) { 00553 //Update Current lifetimes (see RFC 4862 for rules detail) 00554 if (valid_lifetime > (2 * 60 * 60) || valid_lifetime > e->valid_lifetime) { 00555 addr_set_valid_lifetime(cur, e, valid_lifetime); 00556 } else if (e->valid_lifetime <= (2 * 60 * 60)) { 00557 //NOT Update Valid Lifetime 00558 } else { 00559 addr_set_valid_lifetime(cur, e, 2 * 60 * 60); 00560 } 00561 00562 addr_set_preferred_lifetime(cur, e, preferred_lifetime); 00563 ret_val = 0; 00564 } 00565 } 00566 return ret_val; 00567 } 00568 00569 void icmpv6_slaac_prefix_register_trig(struct protocol_interface_info_entry *cur, uint8_t *prefix_ptr, uint8_t prefix_len) 00570 { 00571 00572 //Validate first current list If prefix is already defined adress 00573 ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) { 00574 if (e->source == ADDR_SOURCE_SLAAC && (e->prefix_len == prefix_len) && bitsequal(e->address, prefix_ptr, prefix_len)) { 00575 e->state_timer = 150; 00576 } 00577 } 00578 } 00579 #endif // HAVE_IPV6_ND 00580 00581 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) 00582 { 00583 if_address_entry_t *address_entry; 00584 uint8_t ipv6_address[16]; 00585 //define Autonomous address generation 00586 00587 if (prefix_len != 64) { 00588 return NULL; 00589 } 00590 00591 if (slaac_src == SLAAC_IID_DEFAULT && cur->opaque_slaac_iids && addr_opaque_iid_key_is_set()) { 00592 slaac_src = SLAAC_IID_OPAQUE; 00593 } 00594 00595 memcpy(ipv6_address, prefix_ptr, 8); 00596 switch (slaac_src) { 00597 case SLAAC_IID_DEFAULT: 00598 case SLAAC_IID_FIXED: 00599 memcpy(ipv6_address + 8, cur->iid_slaac, 8); 00600 break; 00601 case SLAAC_IID_EUI64: 00602 memcpy(ipv6_address + 8, cur->iid_eui64, 8); 00603 break; 00604 case SLAAC_IID_OPAQUE: 00605 addr_generate_opaque_iid(cur, ipv6_address); 00606 break; 00607 case SLAAC_IID_6LOWPAN_SHORT: 00608 if (cur->nwk_id != IF_6LoWPAN || !cur->mac_parameters) { 00609 return NULL; 00610 } 00611 memcpy(ipv6_address + 8, ADDR_SHORT_ADR_SUFFIC, 6); 00612 common_write_16_bit(cur->lowpan_desired_short_address, ipv6_address + 14); 00613 break; 00614 00615 default: 00616 return NULL; 00617 } 00618 00619 //tr_debug("Add add: %s", trace_ipv6(ipv6_address)); 00620 00621 address_entry = addr_add(cur, ipv6_address, 64, ADDR_SOURCE_SLAAC, valid_lifetime, preferred_lifetime, skip_dad); 00622 if (address_entry) { 00623 address_entry->cb = NULL; 00624 } 00625 return address_entry; 00626 } 00627 00628 #ifdef HAVE_IPV6_ND 00629 static buffer_t *icmpv6_ra_handler(buffer_t *buf) 00630 { 00631 protocol_interface_info_entry_t *cur; 00632 uint8_t flags, hoplimit; 00633 uint32_t reachable_time, retrans_timer; 00634 uint16_t data_len, router_lifetime; 00635 uint8_t *dptr; 00636 ipv6_neighbour_t *ncache_entry = NULL; 00637 int_fast8_t preference = 0; 00638 uint32_t longest_route_lifetime = 0; 00639 00640 if (!buf) { 00641 return NULL; 00642 } 00643 00644 cur = buf->interface ; 00645 00646 // If both route and prefix receive are disabled do not process any RA options 00647 if (!cur->recv_ra_routes && !cur->recv_ra_prefixes) { 00648 return buffer_free(buf); 00649 } 00650 00651 // Drop RA If LL address generation is not ready 00652 if (addr_interface_get_ll_address(cur, NULL, 0) < 0) { 00653 return buffer_free(buf); 00654 } 00655 00656 if (cur->nwk_id == IF_6LoWPAN) { 00657 // XXX this check needs to be for host bootstrap only 00658 if ((cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) == 0) { 00659 if (protocol_6lowpan_interface_compare_cordinator_netid(cur, &(buf->src_sa .address [8])) != 0) { 00660 return buffer_free(buf); 00661 } 00662 } 00663 } 00664 00665 if (!addr_is_ipv6_link_local(buf->src_sa .address ) || buf->options .hop_limit != 255 || buf->options .code != 0) { 00666 return buffer_free(buf); 00667 } 00668 00669 if (!icmpv6_options_well_formed_in_buffer(buf, 12)) { 00670 tr_debug("Malformed RA"); 00671 return buffer_free(buf); 00672 } 00673 00674 /* Token-bucket rate limiting */ 00675 if (!cur->icmp_ra_tokens) { 00676 return buffer_free(buf); 00677 } 00678 cur->icmp_ra_tokens--; 00679 00680 data_len = buffer_data_length(buf); 00681 dptr = buffer_data_pointer(buf); 00682 //tr_debug("RX RA: %s", trace_ipv6(buf->src_sa.address)); 00683 00684 /* XXX we always set variables based on RAs; fine for a host, 00685 * but wrong/iffy for a router. But then so is doing SLAAC as a 00686 * router... 00687 */ 00688 hoplimit = *dptr++; 00689 if (hoplimit) { 00690 cur->cur_hop_limit = hoplimit; 00691 } 00692 00693 //Read Flags 00694 flags = *dptr++; 00695 router_lifetime = common_read_16_bit(dptr); 00696 dptr += 2; 00697 00698 reachable_time = common_read_32_bit(dptr); 00699 dptr += 4; 00700 if (reachable_time != 0 && reachable_time != cur->base_reachable_time) { 00701 protocol_stack_interface_set_reachable_time(cur, reachable_time); 00702 } 00703 00704 retrans_timer = common_read_32_bit(dptr); 00705 dptr += 4; 00706 if (retrans_timer != 0) { 00707 cur->ipv6_neighbour_cache.retrans_timer = retrans_timer; 00708 } 00709 00710 const uint8_t *mtu_option = icmpv6_find_option_in_buffer(buf, 12, ICMPV6_OPT_MTU, 1); 00711 uint32_t mtu = mtu_option ? common_read_32_bit(mtu_option + 4) : 0; 00712 00713 sockaddr_t ll_addr = { .addr_type = ADDR_NONE }; 00714 const uint8_t *sllao = icmpv6_find_option_in_buffer(buf, 12, ICMPV6_OPT_SRC_LL_ADDR, 0); 00715 if (sllao) { 00716 if (cur->if_llao_parse(cur, sllao, &ll_addr)) { 00717 ncache_entry = ipv6_neighbour_update_unsolicited(&cur->ipv6_neighbour_cache, buf->src_sa .address , ll_addr.addr_type , ll_addr.address ); 00718 } 00719 } 00720 00721 buffer_data_strip_header(buf, 12); 00722 data_len -= 12; 00723 00724 if (cur->nwk_id == IF_6LoWPAN) { 00725 const uint8_t *abro; 00726 bool uptodate; 00727 00728 /* ABRO processing - aiming to separate this from standard processing; only 6LRs need to use ABROs */ 00729 abro = icmpv6_find_option_in_buffer(buf, 0, ICMPV6_OPT_AUTHORITATIVE_BORDER_RTR, 3); 00730 if (abro) { 00731 uptodate = nd_ra_process_abro(cur, buf, abro + 2, flags, router_lifetime); 00732 /* If ABRO processing indicated stale info, skip normal processing */ 00733 if (!uptodate) { 00734 goto drop; 00735 } 00736 #ifndef NO_RADV_TX 00737 if (hoplimit != 0) { 00738 cur->adv_cur_hop_limit = hoplimit; 00739 } 00740 if (reachable_time != 0) { 00741 cur->adv_reachable_time = reachable_time; 00742 } 00743 if (retrans_timer != 0) { 00744 cur->adv_retrans_timer = retrans_timer; 00745 } 00746 if (mtu != 0) { 00747 cur->adv_link_mtu = mtu; 00748 } 00749 #endif 00750 } 00751 } 00752 if (cur->recv_ra_routes) { 00753 if (router_lifetime) { 00754 tr_debug("Possible Default Router"); 00755 switch (flags & RA_PRF_MASK) { 00756 case RA_PRF_LOW: 00757 preference = -1; 00758 break; 00759 case RA_PRF_HIGH: 00760 preference = +1; 00761 break; 00762 default: 00763 preference = 0; 00764 break; // invalid is treated as 0 00765 } 00766 if (router_lifetime > longest_route_lifetime) { 00767 longest_route_lifetime = router_lifetime; 00768 } 00769 } 00770 ipv6_route_add(NULL, 0, cur->id, buf->src_sa .address , ROUTE_RADV, router_lifetime, preference); 00771 } 00772 00773 if (mtu >= IPV6_MIN_LINK_MTU && mtu <= cur->max_link_mtu) { 00774 cur->ipv6_neighbour_cache.link_mtu = mtu; 00775 } 00776 00777 //Scan All options 00778 while (data_len) { 00779 uint8_t type = *dptr++; 00780 uint16_t length = *dptr++ * 8; 00781 00782 if (type == ICMPV6_OPT_PREFIX_INFO && cur->recv_ra_prefixes && length == 32) { 00783 uint8_t *ptr = dptr; 00784 uint8_t prefix_length = *ptr++; 00785 uint8_t prefix_flags = *ptr++; 00786 00787 uint32_t valid_lifetime = common_read_32_bit(ptr); 00788 ptr += 4; 00789 uint32_t preferred_lifetime = common_read_32_bit(ptr); 00790 ptr += 8; //Update 32-bit time and reserved 32-bit 00791 const uint8_t *prefix_ptr = ptr; 00792 00793 //Check is L Flag active 00794 if (prefix_flags & PIO_L) { 00795 //define ONLink Route Information 00796 //tr_debug("Register On Link Prefix to routing table"); 00797 ipv6_route_add(prefix_ptr, prefix_length, cur->id, NULL, ROUTE_RADV, valid_lifetime, 0); 00798 } 00799 00800 //Check if A-Flag 00801 if (prefix_flags & PIO_A) { 00802 if (icmpv6_slaac_prefix_update(cur, prefix_ptr, prefix_length, valid_lifetime, preferred_lifetime) != 0) { 00803 ipv6_interface_slaac_handler(cur, prefix_ptr, prefix_length, valid_lifetime, preferred_lifetime); 00804 } 00805 00806 //tr_debug("Prefix: %s", trace_ipv6(prefix_ptr)); 00807 } 00808 00809 // If the R flag is set and we have SLLAO, let's add a neighbour cache entry. 00810 // This helps reduce RPL noise with source routing - may otherwise be good. 00811 // Note that existence of a neighbour cache entry doesn't affect routing - we 00812 // won't use it unless we otherwise decide they're on-link, eg from a source 00813 // routing header directing to them 00814 if ((prefix_flags & PIO_R) && ll_addr.addr_type != ADDR_NONE ) { 00815 ipv6_neighbour_update_unsolicited(&cur->ipv6_neighbour_cache, prefix_ptr, ll_addr.addr_type , ll_addr.address ); 00816 } 00817 } else if (type == ICMPV6_OPT_ROUTE_INFO && cur->recv_ra_routes) { 00818 uint8_t prefix_length = dptr[0]; 00819 uint8_t route_flags = dptr[1]; 00820 uint32_t route_lifetime = common_read_32_bit(dptr + 2); 00821 uint8_t *prefix_ptr = dptr + 6; 00822 // Check option is long enough for prefix 00823 if (length < 8 + (prefix_length + 7u) / 8) { 00824 goto next_option; 00825 } 00826 switch (route_flags & RA_PRF_MASK) { 00827 case RA_PRF_LOW: 00828 preference = -1; 00829 break; 00830 case RA_PRF_MEDIUM: 00831 preference = 0; 00832 break; 00833 case RA_PRF_HIGH: 00834 preference = +1; 00835 break; 00836 default: 00837 goto next_option; // invalid not accepted 00838 } 00839 if (route_lifetime > longest_route_lifetime) { 00840 longest_route_lifetime = route_lifetime; 00841 } 00842 00843 //Call route Update 00844 tr_info("Route: %s Lifetime: %lu Pref: %d", trace_ipv6_prefix(prefix_ptr, prefix_length), (unsigned long) route_lifetime, preference); 00845 if (route_lifetime) { 00846 ipv6_route_add(prefix_ptr, prefix_length, cur->id, buf->src_sa .address , ROUTE_RADV, route_lifetime, preference); 00847 } else { 00848 ipv6_route_delete(prefix_ptr, prefix_length, cur->id, buf->src_sa .address , ROUTE_RADV); 00849 } 00850 } else if (type == ICMPV6_OPT_6LOWPAN_CONTEXT) { 00851 nd_ra_process_lowpan_context_option(cur, dptr - 2); 00852 } 00853 next_option: 00854 //UPdate length and 00855 data_len -= length; 00856 dptr += length - 2; 00857 } 00858 00859 /* RFC 4861 says to always set IsRouter on receipt of any RA, but this 00860 * seems to make more sense - a shutting-down router (sending the final 00861 * MAX_FINAL_RTR_ADVERTISEMENTS), or a router advertising only prefixes 00862 * shouldn't really be marked as a router. So only set IsRouter if 00863 * a route was advertised (with non-0 lifetime). 00864 */ 00865 if (longest_route_lifetime) { 00866 if (!ncache_entry) { 00867 ncache_entry = ipv6_neighbour_lookup(&cur->ipv6_neighbour_cache, buf->src_sa .address ); 00868 } 00869 00870 if (ncache_entry) { 00871 ncache_entry->is_router = true; 00872 } 00873 } 00874 00875 drop: 00876 return buffer_free(buf); 00877 } 00878 00879 void icmpv6_recv_ra_routes(protocol_interface_info_entry_t *cur, bool enable) 00880 { 00881 if (cur->recv_ra_routes != enable) { 00882 cur->recv_ra_routes = enable; 00883 if (!enable) { 00884 ipv6_route_table_remove_info(cur->id, ROUTE_RADV, NULL); 00885 } 00886 } 00887 } 00888 00889 void icmpv6_recv_ra_prefixes(protocol_interface_info_entry_t *cur, bool enable) 00890 { 00891 if (cur->recv_ra_prefixes != enable) { 00892 cur->recv_ra_prefixes = enable; 00893 if (!enable) { 00894 addr_set_non_preferred(cur, ADDR_SOURCE_SLAAC); 00895 } 00896 } 00897 } 00898 00899 static buffer_t *icmpv6_redirect_handler(buffer_t *buf, protocol_interface_info_entry_t *cur) 00900 { 00901 const uint8_t *ptr = buffer_data_pointer(buf); 00902 const uint8_t *tgt = ptr + 4; 00903 const uint8_t *dest = ptr + 20; 00904 sockaddr_t tgt_ll = { .addr_type = ADDR_NONE }; 00905 00906 if (buf->options .hop_limit != 255) { 00907 goto drop; 00908 } 00909 00910 if (!addr_is_ipv6_link_local(buf->src_sa .address )) { 00911 goto drop; 00912 } 00913 00914 if (buf->options .code != 0) { 00915 goto drop; 00916 } 00917 00918 if (!icmpv6_options_well_formed_in_buffer(buf, 36)) { 00919 goto drop; 00920 } 00921 00922 if (addr_is_ipv6_multicast(dest)) { 00923 goto drop; 00924 } 00925 00926 const uint8_t *tllao = icmpv6_find_option_in_buffer(buf, 36, ICMPV6_OPT_TGT_LL_ADDR, 0); 00927 if (tllao) { 00928 cur->if_llao_parse(cur, tllao, &tgt_ll); 00929 } 00930 ipv6_destination_redirect(tgt, buf->src_sa .address , dest, buf->interface ->id, tgt_ll.addr_type , tgt_ll.address ); 00931 return buffer_free(buf); 00932 00933 drop: 00934 tr_warn("Redirect drop"); 00935 return buffer_free(buf); 00936 } 00937 00938 static buffer_t *icmpv6_na_handler(buffer_t *buf) 00939 { 00940 protocol_interface_info_entry_t *cur; 00941 uint8_t *dptr = buffer_data_pointer(buf); 00942 uint8_t flags; 00943 const uint8_t *target; 00944 const uint8_t *tllao; 00945 if_address_entry_t *addr_entry; 00946 ipv6_neighbour_t *neighbour_entry; 00947 00948 //"Parse NA at IPv6\n"); 00949 00950 if (buf->options .code != 0 || buf->options .hop_limit != 255) { 00951 goto drop; 00952 } 00953 00954 if (!icmpv6_options_well_formed_in_buffer(buf, 20)) { 00955 goto drop; 00956 } 00957 00958 // Skip the 4 reserved bytes 00959 flags = *dptr; 00960 dptr += 4; 00961 00962 // Note the target IPv6 address 00963 target = dptr; 00964 00965 if (addr_is_ipv6_multicast(target)) { 00966 goto drop; 00967 } 00968 00969 /* Solicited flag must be clear if sent to a multicast address */ 00970 if (addr_is_ipv6_multicast(buf->dst_sa .address ) && (flags & NA_S)) { 00971 goto drop; 00972 } 00973 00974 cur = buf->interface ; 00975 00976 /* RFC 4862 5.4.4 DAD checks */ 00977 addr_entry = addr_get_entry(cur, target); 00978 if (addr_entry) { 00979 if (addr_entry->tentative) { 00980 tr_debug("Received NA for our tentative address"); 00981 addr_duplicate_detected(cur, target); 00982 } else { 00983 tr_debug("NA received for our own address: %s", trace_ipv6(target)); 00984 } 00985 goto drop; 00986 } 00987 00988 if (cur->ipv6_neighbour_cache.recv_na_aro) { 00989 const uint8_t *aro = icmpv6_find_option_in_buffer(buf, 20, ICMPV6_OPT_ADDR_REGISTRATION, 2); 00990 if (aro) { 00991 icmpv6_na_aro_handler(cur, aro, buf->dst_sa .address ); 00992 } 00993 } 00994 00995 /* No need to create a neighbour cache entry if one doesn't already exist */ 00996 neighbour_entry = ipv6_neighbour_lookup(&cur->ipv6_neighbour_cache, target); 00997 if (!neighbour_entry) { 00998 goto drop; 00999 } 01000 01001 tllao = icmpv6_find_option_in_buffer(buf, 20, ICMPV6_OPT_TGT_LL_ADDR, 0); 01002 if (!tllao || !cur->if_llao_parse(cur, tllao, &buf->dst_sa )) { 01003 buf->dst_sa .addr_type = ADDR_NONE ; 01004 } 01005 01006 ipv6_neighbour_update_from_na(&cur->ipv6_neighbour_cache, neighbour_entry, flags, buf->dst_sa .addr_type , buf->dst_sa .address ); 01007 if (ws_info(cur) && neighbour_entry->state == IP_NEIGHBOUR_REACHABLE) { 01008 tr_debug("NA neigh update"); 01009 ws_common_neighbor_update(cur, target); 01010 } 01011 01012 drop: 01013 return buffer_free(buf); 01014 } 01015 #endif // HAVE_IPV6_ND 01016 01017 buffer_t *icmpv6_up(buffer_t *buf) 01018 { 01019 protocol_interface_info_entry_t *cur = NULL; 01020 uint8_t *dptr = buffer_data_pointer(buf); 01021 uint16_t data_len = buffer_data_length(buf); 01022 01023 cur = buf->interface ; 01024 01025 if (buf->options .ll_security_bypass_rx ) { 01026 tr_debug("ICMP: Drop by EP"); 01027 goto drop; 01028 } 01029 01030 if (data_len < 4) { 01031 //tr_debug("Ic1"); 01032 goto drop; 01033 01034 } 01035 01036 buf->options .type = *dptr++; 01037 buf->options .code = *dptr++; 01038 01039 /* Check FCS first */ 01040 if (buffer_ipv6_fcf(buf, IPV6_NH_ICMPV6)) { 01041 tr_warn("ICMP cksum error!"); 01042 protocol_stats_update(STATS_IP_CKSUM_ERROR, 1); 01043 goto drop; 01044 } 01045 01046 //Skip ICMP Header Static 4 bytes length 01047 buffer_data_strip_header(buf, 4); 01048 01049 if (cur->if_icmp_handler) { 01050 bool bounce = false; 01051 buf = cur->if_icmp_handler(cur, buf, &bounce); 01052 if (!buf || bounce) { 01053 return buf; 01054 } 01055 } 01056 01057 switch (buf->options .type ) { 01058 #ifdef HAVE_IPV6_ND 01059 case ICMPV6_TYPE_INFO_RS: 01060 buf = icmpv6_rs_handler(buf, cur); 01061 break; 01062 01063 case ICMPV6_TYPE_INFO_RA: 01064 buf = icmpv6_ra_handler(buf); 01065 break; 01066 01067 case ICMPV6_TYPE_INFO_NS: 01068 buf = icmpv6_ns_handler(buf); 01069 break; 01070 01071 case ICMPV6_TYPE_INFO_NA: 01072 buf = icmpv6_na_handler(buf); 01073 break; 01074 01075 case ICMPV6_TYPE_INFO_REDIRECT: 01076 buf = icmpv6_redirect_handler(buf, cur); 01077 break; 01078 #endif 01079 01080 case ICMPV6_TYPE_INFO_ECHO_REQUEST: 01081 tr_debug("ICMP echo request from: %s", trace_ipv6(buf->src_sa .address )); 01082 buf = icmpv6_echo_request_handler(buf); 01083 break; 01084 01085 case ICMPV6_TYPE_INFO_ECHO_REPLY: 01086 ipv6_neighbour_reachability_confirmation(buf->src_sa .address , buf->interface ->id); 01087 /* fall through */ 01088 01089 case ICMPV6_TYPE_ERROR_DESTINATION_UNREACH: 01090 #ifdef HAVE_RPL_ROOT 01091 if (buf->options .type == ICMPV6_TYPE_ERROR_DESTINATION_UNREACH && buf->options .code == ICMPV6_CODE_DST_UNREACH_SRC_RTE_HDR_ERR) { 01092 buf = rpl_control_source_route_error_handler(buf, cur); 01093 } 01094 #endif 01095 /* no break */ 01096 01097 default: 01098 if (buf) { 01099 buf->info = (buffer_info_t)(B_FROM_ICMP | B_TO_APP | B_DIR_UP); 01100 buf->options .type = (uint8_t) SOCKET_FAMILY_IPV6; 01101 buf->options .code = IPV6_NH_ICMPV6; 01102 buf->dst_sa .port = 0xffff; 01103 /* Put back ICMP header */ 01104 buffer_data_reserve_header(buf, 4); 01105 } 01106 break; 01107 01108 case ICMPV6_TYPE_INFO_MCAST_LIST_REPORT: 01109 buf = mld_report_handler(buf, cur); 01110 break; 01111 01112 case ICMPV6_TYPE_INFO_MCAST_LIST_QUERY: 01113 buf = mld_query_handler(buf, cur); 01114 break; 01115 01116 #ifndef NO_IPV6_PMTUD 01117 case ICMPV6_TYPE_ERROR_PACKET_TOO_BIG: 01118 buf = icmpv6_packet_too_big_handler(buf); 01119 break; 01120 #endif 01121 01122 #ifdef HAVE_RPL 01123 case ICMPV6_TYPE_INFO_RPL_CONTROL: 01124 buf = rpl_control_handler(buf); 01125 break; 01126 #endif 01127 01128 #ifdef HAVE_MPL 01129 case ICMPV6_TYPE_INFO_MPL_CONTROL: 01130 buf = mpl_control_handler(buf, cur); 01131 break; 01132 #endif 01133 01134 #ifdef HAVE_6LOWPAN_BORDER_ROUTER 01135 case ICMPV6_TYPE_INFO_DAR: 01136 01137 if (cur->nwk_id == IF_6LoWPAN) { 01138 if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { 01139 buf = nd_dar_parse(buf, cur); 01140 break; 01141 } 01142 } 01143 goto drop; 01144 #endif 01145 #ifdef HAVE_6LOWPAN_ROUTER 01146 case ICMPV6_TYPE_INFO_DAC: 01147 if (cur->nwk_id == IF_6LoWPAN) { 01148 if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY) { 01149 buf = nd_dac_handler(buf, cur); 01150 break; 01151 } 01152 } 01153 goto drop; 01154 #endif 01155 01156 } 01157 01158 return buf; 01159 01160 drop: 01161 return buffer_free(buf); 01162 } 01163 01164 buffer_t *icmpv6_down(buffer_t *buf) 01165 { 01166 protocol_interface_info_entry_t *cur = buf->interface ; 01167 01168 buf = buffer_headroom(buf, 4); 01169 if (buf) { 01170 uint8_t *dptr; 01171 dptr = buffer_data_reserve_header(buf, 4); 01172 buf->info = (buffer_info_t)(B_FROM_ICMP | B_TO_IPV6 | B_DIR_DOWN); 01173 01174 if (buf->src_sa .addr_type != ADDR_IPV6 ) { 01175 if (addr_interface_select_source(cur, buf->src_sa .address , buf->dst_sa .address , 0) != 0) { 01176 tr_err("ICMP:InterFace Address Get Fail--> free Buffer"); 01177 return buffer_free(buf); 01178 } else { 01179 buf->src_sa .addr_type = ADDR_IPV6 ; 01180 } 01181 01182 } 01183 01184 *dptr++ = buf->options .type ; 01185 *dptr++ = buf->options .code ; 01186 common_write_16_bit(0, dptr); 01187 common_write_16_bit(buffer_ipv6_fcf(buf, IPV6_NH_ICMPV6), dptr); 01188 buf->options .type = IPV6_NH_ICMPV6; 01189 buf->options .code = 0; 01190 buf->options .traffic_class &= ~IP_TCLASS_ECN_MASK; 01191 } 01192 return (buf); 01193 } 01194 01195 #ifdef HAVE_IPV6_ND 01196 buffer_t *icmpv6_build_rs(protocol_interface_info_entry_t *cur, const uint8_t *dest) 01197 { 01198 01199 buffer_t *buf = buffer_get(127); 01200 if (!buf) { 01201 return NULL; 01202 } 01203 01204 const uint8_t *src_address; 01205 uint8_t *ptr = buffer_data_pointer(buf); 01206 01207 memcpy(buf->dst_sa .address , dest ? dest : ADDR_LINK_LOCAL_ALL_ROUTERS, 16); 01208 buf->dst_sa .addr_type = ADDR_IPV6 ; 01209 01210 //select Address by Interface pointer and destination 01211 src_address = addr_select_source(cur, buf->dst_sa .address , 0); 01212 if (!src_address) { 01213 tr_debug("No source address defined"); 01214 return buffer_free(buf); 01215 } 01216 01217 memcpy(buf->src_sa .address , src_address, 16); 01218 buf->src_sa .addr_type = ADDR_IPV6 ; 01219 01220 buf->options .type = ICMPV6_TYPE_INFO_RS; 01221 buf->options .code = 0; 01222 buf->options .hop_limit = 255; 01223 ptr = common_write_32_bit(0, ptr); 01224 01225 /* RFC 6775 mandates SLLAO in RS */ 01226 ptr = icmpv6_write_icmp_lla(cur, ptr, ICMPV6_OPT_SRC_LL_ADDR, true, src_address); 01227 01228 buf->buf_end = ptr - buf->buf ; 01229 buf->interface = cur; 01230 buf->info = (buffer_info_t)(B_FROM_ICMP | B_TO_ICMP | B_DIR_DOWN); 01231 01232 return buf; 01233 } 01234 01235 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) 01236 { 01237 dptr += cur->if_llao_write(cur, dptr, icmp_opt, must, ip_addr); 01238 01239 return dptr; 01240 } 01241 01242 /* 01243 * Write either an ICMPv6 Prefix Information Option for a Router Advertisement 01244 * (RFC4861+6275), or an RPL Prefix Information Option (RFC6550). 01245 * Same payload, different type/len. 01246 */ 01247 uint8_t *icmpv6_write_prefix_option(const prefix_list_t *prefixes, uint8_t *dptr, uint8_t rpl_prefix, protocol_interface_info_entry_t *cur) 01248 { 01249 uint8_t flags; 01250 01251 ns_list_foreach(prefix_entry_t, prefix_ptr, prefixes) { 01252 flags = prefix_ptr->options; 01253 if (prefix_ptr->prefix_len == 64) { 01254 /* XXX this seems dubious - shouldn't get_address_with_prefix be called every time? What if the address changes or is deleted? */ 01255 if (prefix_ptr->options & PIO_R) { 01256 const uint8_t *addr = addr_select_with_prefix(cur, prefix_ptr->prefix, prefix_ptr->prefix_len, 0); 01257 if (addr) { 01258 memcpy(prefix_ptr->prefix, addr, 16); 01259 } else { 01260 flags &= ~PIO_R; 01261 } 01262 } 01263 } 01264 if (rpl_prefix) { 01265 *dptr++ = RPL_PREFIX_INFO_OPTION; 01266 *dptr++ = 30; // Length in bytes, excluding these 2 01267 } else { 01268 *dptr++ = ICMPV6_OPT_PREFIX_INFO; 01269 *dptr++ = 4; // Length in 8-byte units 01270 } 01271 01272 *dptr++ = prefix_ptr->prefix_len; //length 01273 *dptr++ = flags; //Flags 01274 dptr = common_write_32_bit(prefix_ptr->lifetime, dptr); 01275 dptr = common_write_32_bit(prefix_ptr->preftime, dptr); 01276 dptr = common_write_32_bit(0, dptr); // Reserved2 01277 memcpy(dptr, prefix_ptr->prefix, 16); 01278 dptr += 16; 01279 } 01280 return dptr; 01281 } 01282 01283 /* 0 1 2 3 01284 * 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 01285 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 01286 * | Type | Length | Reserved | 01287 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 01288 * | MTU | 01289 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 01290 */ 01291 uint8_t *icmpv6_write_mtu_option(uint32_t mtu, uint8_t *dptr) 01292 { 01293 *dptr++ = ICMPV6_OPT_MTU; 01294 *dptr++ = 1; // length 01295 dptr = common_write_16_bit(0, dptr); 01296 dptr = common_write_32_bit(mtu, dptr); 01297 return dptr; 01298 } 01299 01300 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) 01301 { 01302 if (!cur || addr_is_ipv6_multicast(target_addr)) { 01303 return NULL; 01304 } 01305 01306 buffer_t *buf = buffer_get(127); 01307 if (!buf) { 01308 return buf; 01309 } 01310 01311 buf->options .type = ICMPV6_TYPE_INFO_NS; 01312 buf->options .code = 0; 01313 buf->options .hop_limit = 255; 01314 01315 uint8_t *ptr = buffer_data_pointer(buf); 01316 ptr = common_write_32_bit(0, ptr); 01317 memcpy(ptr, target_addr, 16); 01318 ptr += 16; 01319 01320 if (aro) { 01321 *ptr++ = ICMPV6_OPT_ADDR_REGISTRATION; 01322 *ptr++ = 2; 01323 *ptr++ = aro->status; /* Should be ARO_SUCCESS in an NS */ 01324 *ptr++ = 0; 01325 ptr = common_write_16_bit(0, ptr); 01326 ptr = common_write_16_bit(aro->lifetime, ptr); 01327 memcpy(ptr, aro->eui64, 8); 01328 ptr += 8; 01329 } 01330 01331 if (unicast) { 01332 memcpy(buf->dst_sa .address , target_addr, 16); 01333 } else { 01334 memcpy(buf->dst_sa .address , ADDR_MULTICAST_SOLICITED, 13); 01335 memcpy(buf->dst_sa .address + 13, target_addr + 13, 3); 01336 } 01337 buf->dst_sa .addr_type = ADDR_IPV6 ; 01338 01339 if (unspecified_source) { 01340 memset(buf->src_sa .address , 0, 16); 01341 } else { 01342 /* RFC 4861 7.2.2. says we should use the source of traffic prompting the NS, if possible */ 01343 /* This is also used to specify the address for ARO messages */ 01344 if (aro || (prompting_src_addr && addr_is_assigned_to_interface(cur, prompting_src_addr))) { 01345 memcpy(buf->src_sa .address , prompting_src_addr, 16); 01346 } else { 01347 /* Otherwise, according to RFC 4861, we could use any address. 01348 * But there is a 6LoWPAN/RPL hiccup - a node may have registered 01349 * to us with an ARO, and we might send it's global address a NUD 01350 * probe. But it doesn't know _our_ global address, which default 01351 * address selection would favour. 01352 * If it was still a host, we'd get away with using our global 01353 * address, as we'd be its default route, so its reply comes to us. 01354 * But if it's switched to being a RPL router, it would send its 01355 * globally-addressed reply packet up the RPL DODAG. 01356 * Avoid the problem by using link-local source. 01357 * This will still leave us with an asymmetrical connection - its 01358 * global address on-link for us, and we send to it directly (and 01359 * can NUD probe it), whereas it regards us as off-link and will 01360 * go via RPL (and won't probe us). But it will work fine. 01361 */ 01362 if (addr_interface_get_ll_address(cur, buf->src_sa .address , 0) < 0) { 01363 tr_debug("No address for NS"); 01364 return buffer_free(buf); 01365 } 01366 } 01367 /* SLLAO is required if we're sending an ARO */ 01368 /* This rule can be bypassed with flag use_eui64_as_slla_in_aro */ 01369 if (!cur->ipv6_neighbour_cache.use_eui64_as_slla_in_aro) { 01370 ptr = icmpv6_write_icmp_lla(cur, ptr, ICMPV6_OPT_SRC_LL_ADDR, aro, buf->src_sa .address ); 01371 } 01372 /* If ARO Success sending is omitted, MAC ACK is used instead */ 01373 /* Setting callback for receiving ACK from adaptation layer */ 01374 if (aro && cur->ipv6_neighbour_cache.omit_aro_success) { 01375 buf->ack_receive_cb = rpl_control_address_register_done; 01376 } 01377 } 01378 buf->src_sa .addr_type = ADDR_IPV6 ; 01379 01380 /* NS packets are implicitly on-link. If we ever find ourselves sending an 01381 * NS to a global address, it's because we are in some way regarding 01382 * it as on-link. (eg, redirect, RPL source routing header). We force 01383 * transmission as on-link here, regardless of routing table, to avoid any 01384 * potential oddities. 01385 */ 01386 ipv6_buffer_route_to(buf, buf->dst_sa .address , cur); 01387 01388 buffer_data_end_set(buf, ptr); 01389 buf->interface = cur; 01390 buf->info = (buffer_info_t)(B_FROM_ICMP | B_TO_ICMP | B_DIR_DOWN); 01391 01392 return buf; 01393 } 01394 #endif // HAVE_IPV6_ND 01395 01396 void icmpv6_build_echo_req(protocol_interface_info_entry_t *cur, const uint8_t target_addr[16]) 01397 { 01398 const uint8_t *src; 01399 buffer_t *buf = buffer_get(127); 01400 if (!buf) { 01401 return; 01402 } 01403 01404 buf->options .type = ICMPV6_TYPE_INFO_ECHO_REQUEST; 01405 buf->options .code = 0; 01406 buf->options .hop_limit = 255; 01407 01408 uint8_t *ptr = buffer_data_pointer(buf); 01409 memcpy(ptr, target_addr, 16); 01410 ptr += 16; 01411 01412 memcpy(buf->dst_sa .address , target_addr, 16); 01413 buf->dst_sa .addr_type = ADDR_IPV6 ; 01414 //Select Address By Destination 01415 src = addr_select_source(cur, buf->dst_sa .address , 0); 01416 if (src) { 01417 memcpy(buf->src_sa .address , src, 16); 01418 } else { 01419 tr_debug("No address for NS"); 01420 buffer_free(buf); 01421 return; 01422 } 01423 buf->src_sa .addr_type = ADDR_IPV6 ; 01424 buffer_data_end_set(buf, ptr); 01425 buf->interface = cur; 01426 buf->info = (buffer_info_t)(B_FROM_ICMP | B_TO_ICMP | B_DIR_DOWN); 01427 protocol_push(buf); 01428 } 01429 01430 #ifdef HAVE_6LOWPAN_ROUTER 01431 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) 01432 { 01433 if (!cur) { 01434 return NULL; 01435 } 01436 01437 if (!buf) { 01438 buf = buffer_get(4 + 8 + 16); 01439 if (!buf) { 01440 return buf; 01441 } 01442 } 01443 01444 uint8_t *ptr = buffer_data_pointer(buf); 01445 buf->options .type = type; 01446 buf->options .code = 0; 01447 buf->options .hop_limit = 64; /* RFC 6775 MULTIHOP_HOPLIMIT */ 01448 01449 *ptr++ = status; 01450 *ptr++ = 0; 01451 ptr = common_write_16_bit(lifetime, ptr); 01452 memcpy(ptr, eui64, 8); 01453 ptr += 8; 01454 memcpy(ptr, reg_addr, 16); 01455 ptr += 16; 01456 buffer_data_end_set(buf, ptr); 01457 01458 memcpy(buf->dst_sa .address , dest_addr, 16); 01459 buf->dst_sa .addr_type = ADDR_IPV6 ; 01460 01461 const uint8_t *src = addr_select_source(cur, buf->dst_sa .address , 0); 01462 if (src && !addr_is_ipv6_link_local(src)) { 01463 memcpy(buf->src_sa .address , src, 16); 01464 } else { 01465 tr_debug("No address for DAD"); 01466 return buffer_free(buf); 01467 } 01468 buf->src_sa .addr_type = ADDR_IPV6 ; 01469 buf->interface = cur; 01470 buf->info = (buffer_info_t)(B_FROM_ICMP | B_TO_ICMP | B_DIR_DOWN); 01471 01472 return buf; 01473 } 01474 #endif // HAVE_6LOWPAN_ROUTER 01475 01476 #ifdef HAVE_IPV6_ND 01477 /* 01478 * Neighbor Advertisement Message Format 01479 * 01480 * 0 1 2 3 01481 * 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 01482 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 01483 * | Type | Code | Checksum | 01484 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 01485 * |R|S|O| Reserved | 01486 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 01487 * | | 01488 * + + 01489 * | | 01490 * + Target Address + 01491 * | | 01492 * + + 01493 * | | 01494 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 01495 * | Options ... 01496 * +-+-+-+-+-+-+-+-+-+-+-+- 01497 * 01498 * R Router flag. 01499 * S Solicited flag. 01500 * O Override flag. 01501 */ 01502 01503 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]) 01504 { 01505 uint8_t *ptr; 01506 uint8_t flags; 01507 01508 tr_debug("Build NA"); 01509 01510 /* Check if ARO status == success, then sending can be omitted with flag */ 01511 if (aro && cur->ipv6_neighbour_cache.omit_aro_success && aro->status == ARO_SUCCESS) { 01512 tr_debug("Omit success reply"); 01513 return NULL; 01514 } 01515 01516 buffer_t *buf = buffer_get(8 + 16 + 16 + 16); /* fixed, target addr, target ll addr, aro */ 01517 if (!buf) { 01518 return NULL; 01519 } 01520 01521 ptr = buffer_data_pointer(buf); 01522 buf->options .hop_limit = 255; 01523 01524 // Set the ICMPv6 NA type and code fields as per RFC4861 01525 buf->options .type = ICMPV6_TYPE_INFO_NA; 01526 buf->options .code = 0x00; 01527 01528 // If we're sending RAs, then we have to set the Router bit here 01529 // (RFC 4861 makes host trigger action when they see the IsRouter flag 01530 // go from true to false - RAs from us imply "IsRouter", apparently even if 01531 // Router Lifetime is 0. So keep R set as long as we're sending RAs) 01532 flags = icmpv6_radv_is_enabled(cur) ? NA_R : 0; 01533 01534 if (override) { 01535 flags |= NA_O; 01536 } 01537 01538 if (addr_is_ipv6_unspecified(src_addr)) { 01539 // Solicited flag must be 0 if responding to DAD 01540 memcpy(buf->dst_sa .address , ADDR_LINK_LOCAL_ALL_NODES, 16); 01541 } else { 01542 if (solicited) { 01543 flags |= NA_S; 01544 } 01545 01546 /* See RFC 6775 6.5.2 - errors are sent to LL64 address 01547 * derived from EUI-64, success to IP source address */ 01548 if (aro && aro->status != ARO_SUCCESS) { 01549 memcpy(buf->dst_sa .address , ADDR_LINK_LOCAL_PREFIX, 8); 01550 memcpy(buf->dst_sa .address + 8, aro->eui64, 8); 01551 buf->dst_sa .address [8] ^= 2; 01552 } else { 01553 memcpy(buf->dst_sa .address , src_addr, 16); 01554 } 01555 } 01556 buf->dst_sa .addr_type = ADDR_IPV6 ; 01557 01558 /* In theory we could just use addr_select_source(), as RFC 4861 allows 01559 * any address assigned to the interface as source. But RFC 6775 shows LL64 01560 * as the source in its appendix, sending NA to a global address, and our 01561 * lower layers go a bit funny with RPL during bootstrap if we send from a 01562 * global address to a global address. By favouring the target address as 01563 * source, we catch that 6LoWPAN case (the target is LL), as well as making 01564 * it look neater anyway. 01565 */ 01566 if (addr_is_assigned_to_interface(cur, target)) { 01567 memcpy(buf->src_sa .address , target, 16); 01568 } else { 01569 const uint8_t *src = addr_select_source(cur, buf->dst_sa .address , 0); 01570 if (!src) { 01571 tr_debug("No address"); 01572 return buffer_free(buf); 01573 } 01574 memcpy(buf->src_sa .address , src, 16); 01575 } 01576 buf->src_sa .addr_type = ADDR_IPV6 ; 01577 01578 ptr = common_write_32_bit((uint32_t) flags << 24, ptr); 01579 // Set the target IPv6 address 01580 memcpy(ptr, target, 16); 01581 ptr += 16; 01582 01583 // Set the target Link-Layer address 01584 ptr = icmpv6_write_icmp_lla(cur, ptr, ICMPV6_OPT_TGT_LL_ADDR, tllao_required, target); 01585 01586 if (aro) { 01587 *ptr++ = ICMPV6_OPT_ADDR_REGISTRATION; 01588 *ptr++ = 2; 01589 *ptr++ = aro->status; 01590 *ptr++ = 0; 01591 ptr = common_write_16_bit(0, ptr); 01592 ptr = common_write_16_bit(aro->lifetime, ptr); 01593 memcpy(ptr, aro->eui64, 8); 01594 ptr += 8; 01595 } 01596 //Force Next Hop is destination 01597 ipv6_buffer_route_to(buf, buf->dst_sa .address , cur); 01598 01599 buffer_data_end_set(buf, ptr); 01600 buf->info = (buffer_info_t)(B_DIR_DOWN | B_FROM_ICMP | B_TO_ICMP); 01601 buf->interface = cur; 01602 01603 return (buf); 01604 } 01605 01606 #endif // HAVE_IPV6_ND 01607 01608 #ifdef HAVE_IPV6_ND 01609 /* Check whether the options section of an ICMPv6 message is well-formed */ 01610 bool icmpv6_options_well_formed(const uint8_t *dptr, uint_fast16_t dlen) 01611 { 01612 if (dlen % 8) { 01613 return false; 01614 } 01615 01616 while (dlen) { 01617 uint_fast16_t opt_len = dptr[1] * 8; 01618 if (opt_len == 0 || opt_len > dlen) { 01619 return false; 01620 } 01621 dptr += opt_len; 01622 dlen -= opt_len; 01623 } 01624 01625 return true; 01626 } 01627 01628 bool icmpv6_options_well_formed_in_buffer(const buffer_t *buf, uint16_t offset) 01629 { 01630 if (buffer_data_length(buf) < offset) { 01631 return false; 01632 } 01633 01634 return icmpv6_options_well_formed(buffer_data_pointer(buf) + offset, 01635 buffer_data_length(buf) - offset); 01636 } 01637 01638 /* 01639 * Search for the first option of the specified type (and optionally length). 01640 * Caller must have already checked the options are well-formed. 01641 * If optlen is non-zero, then options with different lengths are ignored. 01642 * Note that optlen is in 8-octet units. 01643 */ 01644 const uint8_t *icmpv6_find_option(const uint8_t *dptr, uint_fast16_t dlen, uint8_t option, uint8_t optlen) 01645 { 01646 while (dlen) { 01647 uint8_t type = dptr[0]; 01648 uint8_t len = dptr[1]; 01649 01650 if (type == option && (optlen == 0 || optlen == len)) { 01651 return dptr; 01652 } else { 01653 dptr += len * 8; 01654 dlen -= len * 8; 01655 } 01656 } 01657 return NULL; 01658 01659 } 01660 01661 const uint8_t *icmpv6_find_option_in_buffer(const buffer_t *buf, uint_fast16_t offset, uint8_t option, uint8_t optlen) 01662 { 01663 return icmpv6_find_option(buffer_data_pointer(buf) + offset, 01664 buffer_data_length(buf) - offset, option, optlen); 01665 } 01666 #endif // HAVE_IPV6_ND
Generated on Tue Aug 9 2022 00:37:09 by
1.7.2