Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers icmpv6.c Source File

icmpv6.c

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