Nicolas Borla / Mbed OS BBR_1Ebene
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers icmpv6.c Source File

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