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 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 18:18:37 by
