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.
Dependencies: nRF51_Vdd TextLCD BME280
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 Jul 12 2022 15:15:47 by
