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