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