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