Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers protocol_ipv6.c Source File

protocol_ipv6.c

00001 /*
00002  * Copyright (c) 2012-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 "string.h"
00019 #include "ns_types.h"
00020 #include "ns_list.h"
00021 #include "ns_trace.h"
00022 #include "nsdynmemLIB.h"
00023 #include "Core/include/ns_socket.h"
00024 #include "NWK_INTERFACE/Include/protocol.h"
00025 #include "Common_Protocols/ipv6.h"
00026 #include "Common_Protocols/icmpv6.h"
00027 #include "Common_Protocols/icmpv6_prefix.h"
00028 #include "Common_Protocols/icmpv6_radv.h"
00029 #include "Common_Protocols/ipv6_resolution.h"
00030 #include "Common_Protocols/udp.h"
00031 #include "6LoWPAN/ND/nd_router_object.h" // for gp_address_ functions - better place?
00032 #include "ipv6_stack/ipv6_routing_table.h"
00033 #include "ipv6_stack/protocol_ipv6.h"
00034 #include "Common_Protocols/tcp.h"
00035 #include "Service_Libs/whiteboard/whiteboard.h"
00036 #include "Service_Libs/nd_proxy/nd_proxy.h"
00037 #include "platform/arm_hal_interrupt.h"
00038 #include "common_functions.h"
00039 #include "ethernet_mac_api.h"
00040 
00041 #ifdef HAVE_ETHERNET
00042 
00043 #define TRACE_GROUP "pIP6"
00044 
00045 typedef struct ipv6_interface_prefix_on_link_t {
00046     uint8_t                             prefix[16];                 /*!< destination address */
00047     uint8_t                             prefix_len;
00048     uint32_t                            prefix_valid_ttl;
00049     ns_list_link_t                      link;
00050 } ipv6_interface_prefix_on_link_t;
00051 
00052 typedef struct ipv6_interface_route_on_link_t {
00053     uint8_t                             prefix[16];                 /*!< destination address */
00054     uint8_t                             prefix_len;
00055     uint8_t                             routePrefer;
00056     uint32_t                            prefix_valid_ttl;
00057     ns_list_link_t                      link;
00058 } ipv6_interface_route_on_link_t;
00059 
00060 #define WB_UPDATE_PERIOD_SECONDS            23
00061 
00062 #define ROUTER_SOL_MAX_COUNTER              4
00063 
00064 #define TRACE_GROUP_PROTOCOL_IPv6  "ip6s"
00065 
00066 static void ipv6_stack(buffer_t *b);
00067 
00068 static uint8_t ipv6_nd_rs(protocol_interface_info_entry_t *cur);
00069 
00070 static void ipv6_stack_prefix_on_link_update(protocol_interface_info_entry_t *cur, uint8_t *address);
00071 static void ipv6_nd_bootstrap(protocol_interface_info_entry_t *cur);
00072 static void ipv6_interface_address_cb(protocol_interface_info_entry_t *interface, if_address_entry_t *addr, if_address_callback_t reason);
00073 int ipv6_interface_route_validate(int8_t interface_id, uint8_t *address);
00074 /* These are the advertised on-link prefixes */
00075 static NS_LIST_DEFINE(prefix_on_link, ipv6_interface_prefix_on_link_t, link);
00076 /* These are the advertised Route prefixes */
00077 static NS_LIST_DEFINE(route_on_link, ipv6_interface_route_on_link_t, link);
00078 static prefix_list_t ipv6_prefixs = NS_LIST_INIT(ipv6_prefixs);
00079 
00080 bool tunnel_in_use = false;
00081 
00082 static void ethernet_data_conf_cb(const eth_mac_api_t *api, const eth_data_conf_t *data)
00083 {
00084     (void)data;
00085     (void)api;
00086     //Currently not handled
00087 }
00088 
00089 static void ethernet_data_ind_cb(const eth_mac_api_t *api, const eth_data_ind_t *data)
00090 {
00091     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(api->parent_id);
00092     if (!cur || !cur->if_stack_buffer_handler || !data) {
00093         return;
00094     }
00095 
00096     /* Fast exit for Ethernet - we will tend to get quite a lot of broadcast
00097      * IPv4 traffic, so filter frame type before allocating a buffer.
00098      */
00099     if (data->etehernet_type != ETHERTYPE_IPV6 || data->msduLength == 0) {
00100         return;
00101     }
00102 
00103     buffer_t *buffer = buffer_get_minimal(data->msduLength);
00104     if (!buffer) {
00105         tr_error("RX: out of memory");
00106         return;
00107     }
00108 
00109     buffer->buf_ptr  = buffer->buf_end  = 0;
00110     // Upward direction functions assume no headroom and are trusting that removed bytes are still valid.
00111     // see mac.c:655
00112 
00113     /* Set default flags */
00114     buffer->options .dbm  = data->dbm;
00115     buffer->options .lqi  = data->link_quality;
00116     buffer->interface  = cur;
00117     buffer->info  = (buffer_info_t)(B_TO_IPV6_TXRX | B_FROM_MAC | B_DIR_UP);
00118 
00119     if (cur->eth_mac_api->address_resolution_needed) {
00120         buffer->dst_sa .addr_type  = ADDR_EUI_48 ;
00121         memcpy(buffer->dst_sa .address , data->dstAddress, 6);
00122 
00123         buffer->src_sa .addr_type  = ADDR_EUI_48 ;
00124         memcpy(buffer->src_sa .address , data->srcAddress, 6);
00125     }
00126 
00127     /* Copy packet content */
00128     buffer_data_add(buffer, data->msdu, data->msduLength);
00129 
00130     protocol_push(buffer);
00131 }
00132 
00133 void ipv6_interface_phy_sap_register(protocol_interface_info_entry_t *cur)
00134 {
00135     if (cur->eth_mac_api) {
00136         cur->eth_mac_api->mac_initialize(cur->eth_mac_api, &ethernet_data_conf_cb, &ethernet_data_ind_cb, cur->id);
00137     }
00138 }
00139 
00140 int ipv6_generate_static_gp_setup(protocol_interface_info_entry_t *cur, bool temporaryAddress)
00141 {
00142     int ret_val = -1;
00143     if_address_entry_t *address_entry;
00144     uint8_t static_address[16];
00145 
00146     ns_list_foreach(prefix_entry_t, prefix_ptr, &ipv6_prefixs) {
00147         if (prefix_ptr->options & PIO_A) {
00148             memcpy(static_address, prefix_ptr->prefix, 8);
00149             memcpy(static_address + 8, cur->iid_eui64, 8);
00150             address_entry = addr_add(cur, static_address, 64, ADDR_SOURCE_STATIC, 0xffffffff, 0xffffffff, false);
00151             if (address_entry) {
00152                 address_entry->temporary = temporaryAddress;
00153                 address_entry->cb = ipv6_interface_address_cb;
00154 #ifdef WHITEBOARD
00155                 whiteboard_interface_register(static_address, cur->id);
00156 #endif
00157                 if (cur->ipv6_configure->IPv6_ND_state != IPV6_GP_CONFIG) {
00158                     cur->ipv6_configure->IPv6_ND_state = IPV6_GP_CONFIG;
00159                     cur->global_address_available = true;
00160                 }
00161                 ret_val = 0;
00162             }
00163         }
00164     }
00165     return ret_val;
00166 }
00167 
00168 int ipv6_prefix_router_flag_activate(uint8_t *ipv6_address)
00169 {
00170     prefix_entry_t *entry = icmpv6_prefix_compare(&ipv6_prefixs, ipv6_address, 64);
00171 
00172     if (entry) {
00173         entry->options |= PIO_R;
00174         memcpy(&entry->prefix[8], ipv6_address + 8, 8);
00175         return 0;
00176     }
00177     return -1;
00178 }
00179 
00180 static buffer_t *ethernet_header_build_push(buffer_t *buf, uint16_t ethernet_type, int8_t *status)
00181 {
00182     protocol_interface_info_entry_t *cur = buf->interface ;
00183     *status = -1;
00184     if (cur->nwk_id == IF_IPV6) {
00185         eth_data_req_t req;
00186         req.msduLength = buffer_data_length(buf);
00187         req.msdu = buffer_data_pointer(buf);
00188         req.srcAddress = buf->src_sa .address ;
00189         req.dstAddress = buf->dst_sa .address ;
00190         req.etehernet_type = ethernet_type;
00191         if (cur->eth_mac_api) {
00192             cur->eth_mac_api->data_req(cur->eth_mac_api, &req);
00193             *status = 0;
00194         } else {
00195             *status = -1;
00196         }
00197     }
00198     return buf;
00199 }
00200 
00201 /* Input: Final IP packet for transmission on link.
00202  *        Buffer destination = final destination
00203  *        Buffer source undefined.
00204  *        Route next hop address set.
00205  * Output: Buffer destination+source = link-layer addresses
00206  *         Sent to MAC layer
00207  */
00208 buffer_t *ethernet_down(buffer_t *buf)
00209 {
00210     protocol_interface_info_entry_t *cur = buf->interface ;
00211 
00212     if (!buf->route) {
00213         tr_debug("ethernet_down route");
00214         return buffer_free(buf);
00215     }
00216 
00217     /* Check if we have tunnel interface that does not need address resolution */
00218     if (cur->eth_mac_api->address_resolution_needed) {
00219         const uint8_t *ip_dst = buf->route->route_info.next_hop_addr;
00220 
00221         /* First, check routing to get next hop */
00222         if (addr_is_ipv6_multicast(ip_dst)) {
00223             buf->dst_sa .addr_type  = ADDR_EUI_48 ;
00224             buf->dst_sa .address [0] = 0x33;
00225             buf->dst_sa .address [1] = 0x33;
00226             memcpy(&buf->dst_sa .address [2], ip_dst + 12, 4);
00227         } else { /* unicast */
00228             ipv6_neighbour_t *n = ipv6_interface_resolve_new(cur, buf);
00229             if (!n) {
00230                 return NULL;
00231             }
00232         }
00233         buf->src_sa .addr_type  = ADDR_EUI_48 ;
00234         memcpy(buf->src_sa .address , cur->mac, 6);
00235     }
00236 
00237     buf->info  = (buffer_info_t)(B_FROM_IPV6_TXRX | B_TO_MAC | B_DIR_DOWN);
00238 
00239     return buf;
00240 
00241 }
00242 
00243 /* Return length of option always, and write option if opt_out != NULL */
00244 static uint8_t ethernet_llao_write(protocol_interface_info_entry_t *cur, uint8_t *opt_out, uint8_t opt_type, bool must, const uint8_t *ip_addr)
00245 {
00246     (void) must;
00247     (void) ip_addr;
00248 
00249     if (memcmp(cur->mac, ADDR_EUI64_ZERO, 8) == 0) {
00250         return 0;
00251     }
00252 
00253     if (opt_out) {
00254         opt_out[0] = opt_type;
00255         opt_out[1] = 1;
00256         memcpy(opt_out + 2, cur->mac, 6);
00257     }
00258     return 8;
00259 }
00260 
00261 /* Parse, and return actual size, or 0 if error */
00262 static uint8_t ethernet_llao_parse(protocol_interface_info_entry_t *cur, const uint8_t *opt_in, sockaddr_t *ll_addr_out)
00263 {
00264     (void) cur;
00265     if (opt_in[1] != 1) {
00266         return 0;
00267     }
00268 
00269     ll_addr_out->addr_type  = ADDR_EUI_48 ;
00270     memcpy(ll_addr_out->address , opt_in + 2, 6);
00271 
00272     return 6;
00273 }
00274 
00275 /**
00276  * \fn ethernet_up
00277  *
00278  * \brief Parse IPv6 header received over the Backhaul link
00279  *
00280  */
00281 /* Input: MAC payload received from Ethernet or other link (frame type was IPv6)
00282  *        Buffer destination = MAC destination (if actually was Ethernet)
00283  *        Buffer source = MAC source
00284  * Output: LL broadcast/multicast flags set based on addresses.
00285  *         Sent to IPv6 forwarding up.
00286  */
00287 static buffer_t *ethernet_up(buffer_t *buf)
00288 {
00289     if (buf->dst_sa .addr_type  == ADDR_EUI_48  && (buf->dst_sa .address [0] & 1)) {
00290         if (memcmp(buf->dst_sa .address , (const uint8_t[]) {
00291         0xff, 0xff, 0xff, 0xff, 0xff, 0xff
00292     }, 6) == 0)
00293         buf->options .ll_broadcast_rx  = true;
00294         else {
00295             buf->options .ll_multicast_rx  = true;
00296         }
00297     }
00298     buf->ip_routed_up = true;
00299     buf->info  = (buffer_info_t)(B_DIR_UP | B_FROM_IPV6_TXRX | B_TO_IPV6_FWD);
00300     return buf;
00301 }
00302 
00303 static void ipv6_nd_bootstrap(protocol_interface_info_entry_t *cur)
00304 {
00305     switch (cur->ipv6_configure->IPv6_ND_state) {
00306         case IPV6_LL_CONFIG:
00307             if (addr_interface_set_ll64(cur, ipv6_interface_address_cb) != 0) {
00308                 cur->ipv6_configure->ND_TIMER = 1;
00309             }
00310             break;
00311 
00312         case IPV6_ROUTER_SOLICATION:
00313             tr_debug("Waiting for ICMPv6 Router Advertisement");
00314             if (ipv6_nd_rs(cur)) {
00315                 if (cur->ipv6_configure->routerSolicationRetryCounter != ROUTER_SOL_MAX_COUNTER) {
00316                     cur->ipv6_configure->routerSolicationRetryCounter++;
00317                 }
00318                 cur->ipv6_configure->ND_TIMER = (cur->ipv6_configure->routerSolicationRetryCounter * 25);
00319 
00320             } else {
00321                 cur->ipv6_configure->ND_TIMER = 1;
00322             }
00323             break;
00324 
00325         case IPV6_GP_GEN:
00326             if (ipv6_generate_static_gp_setup(cur, false) != 0) {
00327                 cur->ipv6_configure->ND_TIMER = 1;
00328             }
00329             break;
00330         case IPV6_GP_CONFIG:
00331             break;
00332 
00333         case IPV6_DHCPV6_SOLICATION:
00334 //              if(dhcpv6_non_temporal_address_solication(cur) == 0)
00335 //              {
00336 //                  cur->ipv6_configure->ND_TIMER = 0;
00337 //              }
00338 //              else
00339 //              {
00340 //                  cur->ipv6_configure->ND_TIMER = 1;
00341 //              }
00342             break;
00343 
00344         case IPV6_DHCPV6_ADDRESS_REQUEST:
00345             break;
00346         case IPV6_DHCPV6_ADDRESS_REQ_FAIL:
00347             tr_warn("DHCP ADDRESS_REQ_FAIL");
00348             /*XXX Do what here? */
00349             break;
00350 
00351         case IPV6_READY:
00352             break;
00353     }
00354 }
00355 
00356 
00357 void ipv6_prefix_on_link_list_add_by_interface_address_list(protocol_interface_info_entry_t *cur_Ipv6, protocol_interface_info_entry_t *curRegisteredInterface)
00358 {
00359     ns_list_foreach(if_address_entry_t, e, &curRegisteredInterface->ip_addresses) {
00360         if (addr_ipv6_scope(e->address, curRegisteredInterface) == IPV6_SCOPE_GLOBAL) {
00361             ipv6_stack_prefix_on_link_update(cur_Ipv6, e->address);
00362         }
00363     }
00364 }
00365 
00366 static void ipv6_stack_prefix_on_link_update(protocol_interface_info_entry_t *cur, uint8_t *address)
00367 {
00368     if (!cur->global_address_available) {
00369         return;
00370     }
00371 
00372     if (addr_interface_gp_prefix_compare(cur, address) != 0) {
00373         ipv6_interface_prefix_on_link_t *new_entry = 0;
00374         ns_list_foreach(ipv6_interface_prefix_on_link_t, tmp_prefix, &prefix_on_link) {
00375             if (memcmp(tmp_prefix->prefix, address, 8) == 0) {
00376                 return;
00377             }
00378         }
00379 
00380         new_entry = ns_dyn_mem_alloc(sizeof(ipv6_interface_prefix_on_link_t));
00381         if (new_entry) {
00382             memset(new_entry->prefix, 0, 16);
00383             memcpy(new_entry->prefix, address, 8);
00384 
00385             new_entry->prefix_len = 64;
00386             // Treat the prefix like a "route", so 3 * advert interval, not 30 days
00387             new_entry->prefix_valid_ttl = (UINT32_C(3) * icmpv6_radv_max_rtr_adv_interval(cur)) / 10;
00388             ns_list_add_to_end(&prefix_on_link, new_entry);
00389             icmpv6_restart_router_advertisements(cur, ADDR_UNSPECIFIED);
00390         }
00391     }
00392 }
00393 
00394 void ipv6_stack_route_advert_update(uint8_t *address, uint8_t prefixLength, uint8_t routePrefer)
00395 {
00396     protocol_interface_info_entry_t *cur = nwk_interface_get_ipv6_ptr();
00397     if (!cur) {
00398         return;
00399     }
00400     if (cur->ipv6_configure->ipv6_stack_mode != NET_IPV6_BOOTSTRAP_STATIC) {
00401         return;
00402     }
00403 
00404     if (addr_interface_gp_prefix_compare(cur, address) == 0) {
00405         return;
00406     }
00407 
00408     ns_list_foreach(ipv6_interface_route_on_link_t, cur_prefix, &route_on_link) {
00409         if ((cur_prefix->prefix_len == prefixLength) && bitsequal(cur_prefix->prefix, address, prefixLength)) {
00410             cur_prefix->routePrefer = routePrefer;
00411             return;
00412         }
00413     }
00414 
00415     ipv6_interface_route_on_link_t *new_entry = ns_dyn_mem_alloc(sizeof(ipv6_interface_route_on_link_t));
00416     if (new_entry) {
00417         memset(new_entry->prefix, 0, 16);
00418         memcpy(new_entry->prefix, address, 16);
00419 
00420         new_entry->prefix_len = prefixLength;
00421         new_entry->routePrefer = routePrefer;
00422         // Treat the prefix like a "route", so 3 * advert interval, not 30 days
00423         new_entry->prefix_valid_ttl = (UINT32_C(3) * icmpv6_radv_max_rtr_adv_interval(cur)) / 10;
00424         ns_list_add_to_end(&route_on_link, new_entry);
00425         icmpv6_restart_router_advertisements(cur, ADDR_UNSPECIFIED);
00426     }
00427 }
00428 
00429 void ipv6_prefix_on_link_update(uint8_t *address)
00430 {
00431     protocol_interface_info_entry_t *cur = nwk_interface_get_ipv6_ptr();
00432     if (cur) {
00433         //Call IPv6 Onlink Update
00434         if (cur->ipv6_configure->ipv6_stack_mode == NET_IPV6_BOOTSTRAP_STATIC) {
00435             ipv6_stack_prefix_on_link_update(cur, address);
00436         }
00437     }
00438 }
00439 
00440 static void ipv6_stack_prefix_on_link_remove(protocol_interface_info_entry_t *cur, uint8_t *address)
00441 {
00442     ns_list_foreach(ipv6_interface_prefix_on_link_t, cur_prefix, &prefix_on_link) {
00443         if (memcmp(cur_prefix->prefix, address, 8) == 0) {
00444             cur_prefix->prefix_valid_ttl = 0;
00445             icmpv6_restart_router_advertisements(cur, ADDR_UNSPECIFIED);
00446             break;
00447         }
00448     }
00449 }
00450 
00451 void ipv6_prefix_on_link_remove(uint8_t *address)
00452 {
00453     protocol_interface_info_entry_t *cur = nwk_interface_get_ipv6_ptr();
00454     if (cur) {
00455         if (cur->ipv6_configure->ipv6_stack_mode == NET_IPV6_BOOTSTRAP_STATIC) {
00456             ipv6_stack_prefix_on_link_remove(cur, address);
00457         }
00458     }
00459 }
00460 
00461 void ipv6_stack_route_advert_remove(uint8_t *address, uint8_t prefixLength)
00462 {
00463     protocol_interface_info_entry_t *cur = nwk_interface_get_ipv6_ptr();
00464     if (!cur) {
00465         return;
00466     }
00467     if (cur->ipv6_configure->ipv6_stack_mode == NET_IPV6_BOOTSTRAP_STATIC) {
00468         ns_list_foreach(ipv6_interface_route_on_link_t, cur_prefix, &route_on_link) {
00469             if ((cur_prefix->prefix_len == prefixLength) && bitsequal(cur_prefix->prefix, address, prefixLength)) {
00470                 cur_prefix->prefix_valid_ttl = 0;
00471                 icmpv6_restart_router_advertisements(cur, ADDR_UNSPECIFIED);
00472                 break;
00473             }
00474         }
00475     }
00476 }
00477 
00478 void ipv6_prefix_online_list_free(void)
00479 {
00480     ns_list_foreach_safe(ipv6_interface_prefix_on_link_t, cur, &prefix_on_link) {
00481         ns_list_remove(&prefix_on_link, cur);
00482         ns_dyn_mem_free(cur);
00483     }
00484 }
00485 
00486 void ipv6_rote_advert_list_free(void)
00487 {
00488     ns_list_foreach_safe(ipv6_interface_route_on_link_t, cur, &route_on_link) {
00489         ns_list_remove(&route_on_link, cur);
00490         ns_dyn_mem_free(cur);
00491     }
00492 }
00493 
00494 void ipv6_core_slow_timer_event_handle(struct protocol_interface_info_entry *cur)
00495 {
00496     if (cur->ipv6_configure) {
00497         protocol_interface_info_entry_t *curRegisteredInterface;
00498         if (cur->ipv6_configure->wb_table_ttl-- == 1) {
00499             //tr_debug("WB Table TTL");
00500             whiteboard_ttl_update(WB_UPDATE_PERIOD_SECONDS);
00501             cur->ipv6_configure->wb_table_ttl   = WB_UPDATE_PERIOD_SECONDS;
00502         }
00503 
00504         if (cur->ipv6_configure->ipv6_stack_mode == NET_IPV6_BOOTSTRAP_STATIC) {
00505 
00506             if (cur->global_address_available) {
00507                 curRegisteredInterface = protocol_stack_interface_info_get(IF_6LoWPAN);
00508                 if (curRegisteredInterface) {
00509 
00510                     ipv6_prefix_on_link_list_add_by_interface_address_list(cur, curRegisteredInterface);
00511                 }
00512             }
00513         }
00514     }
00515 }
00516 
00517 void ipv6_core_timer_event_handle(protocol_interface_info_entry_t *cur, const uint8_t event)
00518 {
00519     (void)event;
00520     if (cur->ipv6_configure->ND_TIMER) {
00521         if (cur->ipv6_configure->ND_TIMER-- == 1) {
00522             //Call ND State Machine
00523             ipv6_nd_bootstrap(cur);
00524         }
00525     }
00526 }
00527 
00528 int ipv6_prefix_register(uint8_t *prefix_64, uint32_t lifetime, uint32_t prefer_lifetime)
00529 {
00530     prefix_entry_t *new_entry = icmpv6_prefix_add(&ipv6_prefixs, prefix_64, 64, lifetime, prefer_lifetime, (PIO_L | PIO_A));
00531     if (new_entry) {
00532         memset(&new_entry->prefix[8], 0, 8);
00533         new_entry->options = PIO_L | PIO_A;
00534         return 0;
00535     }
00536     return -1;
00537 }
00538 
00539 int ipv6_interface_route_validate(int8_t interface_id, uint8_t *address)
00540 {
00541     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00542     if (!cur) {
00543         return -1;
00544     } else if (!cur->ipv6_configure) {
00545         return -1;
00546     } else if (cur->ipv6_configure->IPv6_ND_state != IPV6_READY) {
00547         return -1;
00548     }
00549 
00550     //Validate route OnLink
00551     ipv6_route_t *route;
00552     route = ipv6_route_choose_next_hop(address, interface_id, NULL);
00553 
00554     //Respond default route only when we have other interface for route
00555     if (route && route->on_link) {
00556         return 0;
00557     }
00558 
00559     return -1;
00560 
00561 }
00562 
00563 int8_t ipv6_interface_up(protocol_interface_info_entry_t *cur)
00564 {
00565     uint8_t ipv6_interface_adr[16];
00566 
00567     if (cur->if_stack_buffer_handler) {
00568         return -1;
00569     }
00570 
00571     if (cur->ipv6_configure->ipv6_stack_mode == NET_IPV6_BOOTSTRAP_STATIC) {
00572         uint32_t lifeTime, prefLifetime;
00573         uint8_t pre_options;
00574         memcpy(&ipv6_interface_adr[0], cur->ipv6_configure->static_prefix64, 8);
00575         memcpy(&ipv6_interface_adr[8], cur->iid_eui64, 8);
00576         prefix_entry_t *new_entry = 0;
00577         // Treat the prefix like a "route", so 3 * advert interval, not 30 days
00578         lifeTime = (UINT32_C(3) * icmpv6_radv_max_rtr_adv_interval(cur)) / 10;
00579         prefLifetime = lifeTime / 2;
00580         pre_options = PIO_L | PIO_A | PIO_R;
00581 
00582         new_entry = icmpv6_prefix_add(&ipv6_prefixs, ipv6_interface_adr, 64, lifeTime, prefLifetime, pre_options);
00583 
00584         if (!new_entry) {
00585             return -1;
00586         }
00587         memcpy(&new_entry->prefix[8], &ipv6_interface_adr[8], 8);
00588         new_entry->options = pre_options;
00589 
00590         ipv6_route_add(ipv6_interface_adr, 64, cur->id, NULL, ROUTE_STATIC, 0xffffffff, 1);
00591 
00592         // Disable RA route and prefix processing until static address has been added to interface
00593         icmpv6_recv_ra_routes(cur, false);
00594         icmpv6_recv_ra_prefixes(cur, false);
00595     }
00596 
00597     cur->ipv6_configure->IPv6_ND_state = IPV6_LL_CONFIG;
00598     cur->ipv6_configure->ND_TIMER = 1;
00599 
00600     cur->ipv6_configure->routerSolicationRetryCounter = 0;
00601     cur->ipv6_configure->wb_table_ttl       = WB_UPDATE_PERIOD_SECONDS;
00602     icmpv6_radv_disable(cur);
00603 
00604     tr_debug("IPV6 interface Base Ready");
00605     cur->if_stack_buffer_handler = ipv6_stack;
00606     cur->if_llao_write = ethernet_llao_write;
00607     cur->if_llao_parse = ethernet_llao_parse;
00608     cur->ipv6_neighbour_cache.max_ll_len = 6;
00609     cur->ipv6_neighbour_cache.link_mtu = cur->max_link_mtu = 1500;
00610     cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ACTIVE;
00611     cur->lowpan_info |= INTERFACE_NWK_ACTIVE;
00612 
00613     // Always want fe80::/64 to be an on-link prefix.
00614     ipv6_route_add(ADDR_LINK_LOCAL_PREFIX, 64, cur->id, NULL, ROUTE_STATIC, 0xFFFFFFFF, 0);
00615 
00616     // Putting a multicast route to ff00::/8 makes sure we can always transmit multicast.
00617     // Interface metric will determine which interface is actually used, if we have multiple.
00618     ipv6_route_add(ADDR_LINK_LOCAL_ALL_NODES, 8, cur->id, NULL, ROUTE_STATIC, 0xFFFFFFFF, -1);
00619 
00620     return 0;
00621 }
00622 
00623 int8_t ipv6_interface_down(protocol_interface_info_entry_t *cur)
00624 {
00625     if (!cur || !(cur->lowpan_info & INTERFACE_NWK_ACTIVE)) {
00626         return -1;
00627     }
00628 
00629     whiteboard_interface_unregister_all_address(cur->id);
00630     icmpv6_prefix_list_free(&ipv6_prefixs);
00631     ipv6_prefix_online_list_free();
00632     ipv6_rote_advert_list_free();
00633     neighbor_cache_flush(&cur->neigh_cache);
00634     ipv6_route_table_remove_interface(cur->id);
00635     protocol_core_interface_info_reset(cur);
00636     cur->ipv6_configure->wb_table_ttl = 0;
00637     cur->lowpan_info &= ~INTERFACE_NWK_ACTIVE;
00638     cur->global_address_available = false;
00639     //Clear all generated proxies
00640     nd_proxy_upstream_interface_unregister(cur->id);
00641 
00642     return 0;
00643 }
00644 
00645 
00646 static uint8_t ipv6_nd_rs(protocol_interface_info_entry_t *cur)
00647 {
00648     buffer_t *buf = icmpv6_build_rs(cur, NULL);
00649     if (buf) {
00650         tr_debug("Push RS to IPV6");
00651         arm_net_protocol_packet_handler(buf, cur);
00652         return 1;
00653     }
00654     return 0;
00655 }
00656 
00657 #ifdef RADV_TX
00658 void ipv6_nd_ra_advert(protocol_interface_info_entry_t *cur, const uint8_t *dest)
00659 {
00660     /* 12 base size, plus allow 8 for MTU and 16 for SLLA */
00661     uint16_t length = 12 + 8 + 16;
00662     length += 32 * ns_list_count(&ipv6_prefixs);
00663     length += 32 * ns_list_count(&prefix_on_link);
00664 
00665     ns_list_foreach(ipv6_interface_route_on_link_t, tmp_route, &route_on_link) {
00666         if (tmp_route->prefix_len < 65) {
00667             length += 16;    // add upper 64-bit
00668         } else {
00669             length += 24;    // add full address
00670         }
00671     }
00672 
00673     buffer_t *buf = buffer_get(length);
00674     if (buf) {
00675         uint8_t *ptr = buffer_data_pointer(buf);
00676 
00677         buf->options .hop_limit  = 255;
00678         buf->options .type  = ICMPV6_TYPE_INFO_RA;
00679         buf->options .code  = 0x00;
00680         *ptr++ = cur->adv_cur_hop_limit;
00681         *ptr++ = cur->rtr_adv_flags;
00682         //Do not advertise default route: set Router Lifetime to 0
00683         ptr = common_write_16_bit(0, ptr);
00684         ptr = common_write_32_bit(cur->adv_reachable_time, ptr);
00685         ptr = common_write_32_bit(cur->adv_retrans_timer, ptr);
00686 
00687         // We don't include our Source Link-Layer address - we're not
00688         // advertising routes, so we don't expect anyone to be talking directly
00689         // to us; we're just acting as an ND proxy. If we put in the SLLAO, we
00690         // add ourselves to their Neighbour Cache unnecessarily. This can be
00691         // reactivated if we start advertising actual routes
00692 #if 0
00693         // Set the source Link-Layer address
00694         ptr = icmpv6_write_icmp_lla(cur, ptr, ICMPV6_OPT_SRC_LL_ADDR);
00695 #endif
00696 
00697         //MTU
00698         if (cur->adv_link_mtu != 0) {
00699             ptr = icmpv6_write_mtu_option(cur->adv_link_mtu, ptr);
00700         }
00701 
00702         //IPv6 Prefixes
00703         ptr = icmpv6_write_prefix_option(&ipv6_prefixs,  ptr, 0, cur);
00704 
00705         // Update our own routing table prefixes in sync with what we're advertising above
00706         ns_list_foreach(prefix_entry_t, pfx, &ipv6_prefixs) {
00707             if (pfx->options & PIO_L) {
00708                 ipv6_route_add(pfx->prefix, pfx->prefix_len, cur->id, NULL, ROUTE_STATIC, pfx->lifetime, 1);
00709             }
00710         }
00711 
00712         ns_list_foreach_safe(ipv6_interface_prefix_on_link_t, pfx, &prefix_on_link) {
00713             ipv6_route_add(pfx->prefix, pfx->prefix_len, cur->id, NULL, ROUTE_STATIC, pfx->prefix_valid_ttl, 0);
00714 
00715             *ptr++ = ICMPV6_OPT_PREFIX_INFO;
00716             *ptr++ = 4; // length
00717             *ptr++ = pfx->prefix_len;
00718             *ptr++ = PIO_L;
00719             ptr = common_write_32_bit(pfx->prefix_valid_ttl, ptr); // Valid Lifetime
00720             ptr = common_write_32_bit(pfx->prefix_valid_ttl >> 1, ptr); // Preferred Lifetime
00721             ptr = common_write_32_bit(0, ptr);
00722             memcpy(ptr, pfx->prefix, 16);
00723             ptr += 16;
00724             if (pfx->prefix_valid_ttl == 0) {
00725                 ns_list_remove(&prefix_on_link, pfx);
00726                 ns_dyn_mem_free(pfx);
00727             }
00728         }
00729 
00730         ns_list_foreach_safe(ipv6_interface_route_on_link_t, tmp_route, &route_on_link) {
00731             uint8_t prefix_bytes;
00732             *ptr++ = ICMPV6_OPT_ROUTE_INFO;
00733             if (tmp_route->prefix_len < 65) {
00734                 *ptr++ = 2;
00735                 prefix_bytes = 8;
00736             } else {
00737                 *ptr++ = 3;
00738                 prefix_bytes = 16;
00739             }
00740             *ptr++ = tmp_route->prefix_len;
00741             *ptr++ = tmp_route->routePrefer;
00742             ptr = common_write_32_bit(tmp_route->prefix_valid_ttl, ptr);
00743             memcpy(ptr, tmp_route->prefix, prefix_bytes);
00744             ptr += prefix_bytes;
00745 
00746             if (tmp_route->prefix_valid_ttl == 0) {
00747                 ns_list_remove(&route_on_link, tmp_route);
00748                 ns_dyn_mem_free(tmp_route);
00749             }
00750         }
00751 
00752         buffer_data_end_set(buf, ptr);
00753         memcpy(buf->dst_sa .address , dest, 16);
00754         /* Source must be LL address (even if non-LL dest) */
00755         if (addr_interface_get_ll_address(cur, buf->src_sa .address , 0)) {
00756             tr_debug("No address defined");
00757             buffer_free(buf);
00758             return;
00759         }
00760         buf->dst_sa .addr_type  = ADDR_IPV6 ;
00761         buf->src_sa .addr_type  = ADDR_IPV6 ;
00762 
00763         buf->interface  = cur;
00764         buf->info  = (buffer_info_t)(B_FROM_ICMP | B_TO_ICMP | B_DIR_DOWN);
00765         arm_net_protocol_packet_handler(buf, cur);
00766     }
00767 }
00768 #endif
00769 
00770 static void ipv6_stack(buffer_t *b)
00771 {
00772     /* Protocol Buffer Handle */
00773     int8_t status;
00774     nwk_interface_id nwk_id = IF_IPV6;
00775     if (b) {
00776         //Save Original Interface id
00777         nwk_id = b->interface ->nwk_id;
00778     }
00779     while (b) {
00780         /* Buffer Direction Select Switch */
00781         if ((b->info  & B_DIR_MASK) == B_DIR_DOWN) {
00782             /* Direction DOWN */
00783             switch (b->info  & B_TO_MASK) {
00784                 case B_TO_ICMP:
00785                     /* Build ICMP Header */
00786                     b = icmpv6_down(b);
00787                     break;
00788 
00789                 case B_TO_UDP:
00790                     /* Build UDP Header */
00791                     b = udp_down(b);
00792                     break;
00793 
00794                 case B_TO_IPV6:
00795                     /* Build IP Header */
00796                     b = ipv6_down(b);
00797                     break;
00798 
00799                 case B_TO_IPV6_FWD:
00800                     /* IPv6 forwarding */
00801                     b = ipv6_forwarding_down(b);
00802                     break;
00803 
00804                 case B_TO_IPV6_TXRX:
00805                     /* Resolution, preparing MAC payload */
00806                     b = ethernet_down(b);
00807                     break;
00808 
00809                 case B_TO_MAC:
00810                     b = ethernet_header_build_push(b, ETHERTYPE_IPV6, &status);
00811                     if (b) {
00812                         //GET Interface Pointer
00813                         //uint8_t *ptr = b->buf + b->buf_ptr;
00814                         //uint16_t len = b->buf_end - b->buf_ptr;
00815                         //ethernet_tx(ptr, len);
00816                         if (status == 0) {
00817                             socket_tx_buffer_event_and_free(b, SOCKET_TX_DONE);
00818                         } else {
00819                             socket_tx_buffer_event_and_free(b, SOCKET_TX_FAIL);
00820                         }
00821                     }
00822                     return;
00823 
00824                 default:
00825                     b = buffer_free(b);
00826                     break;
00827             }
00828         } else {
00829             /* Direction UP */
00830             switch (b->info  & B_TO_MASK) {
00831                 case B_TO_APP:
00832                     socket_up(b);
00833                     b = NULL;
00834                     break;
00835 
00836                 case B_TO_MAC:
00837                     /* Beacon and command frames */
00838                     //b = mac_up(b);
00839                     break;
00840 
00841                 case B_TO_ICMP:
00842                     /* Parse ICMP Message */
00843                     b = icmpv6_up(b);
00844                     break;
00845 
00846                 case B_TO_UDP:
00847                     /* Parse UDP Message */
00848                     b = udp_up(b);
00849                     break;
00850 
00851                 case B_TO_IPV6_FWD:
00852                     /* Handle IP Payload */
00853                     b = ipv6_forwarding_up(b);
00854                     break;
00855 
00856                 case B_TO_IPV6_TXRX:
00857                     /* Handle MAC Payload */
00858                     b = ethernet_up(b);
00859                     break;
00860 
00861                 case B_TO_TCP:
00862                     //tr_debug("--> TCP_up()");
00863                     b = tcp_up(b);
00864                     break;
00865 
00866                 default:
00867                     tr_debug("LLL");
00868                     b = buffer_free(b);
00869                     break;
00870             }
00871         }
00872 
00873         if (b) {
00874             //Check If Stack forward packet to different interface
00875             if (b->interface ->nwk_id != nwk_id) {
00876                 protocol_push(b);
00877                 b = 0;
00878             }
00879         }
00880     }
00881 }
00882 
00883 static void ipv6_interface_address_cb(protocol_interface_info_entry_t *interface, if_address_entry_t *addr, if_address_callback_t reason)
00884 {
00885     tr_debug("Interface ID: %i, ipv6: %s", interface->id, trace_ipv6(addr->address));
00886 
00887     switch (reason) {
00888         case ADDR_CALLBACK_DAD_COMPLETE:
00889             tr_debug("DAD OK");
00890             switch (interface->ipv6_configure->IPv6_ND_state) {
00891                 case IPV6_LL_CONFIG:
00892                     if (interface->ipv6_configure->ipv6_stack_mode == NET_IPV6_BOOTSTRAP_STATIC) {
00893                         interface->ipv6_configure->IPv6_ND_state = IPV6_GP_GEN;
00894                     } else {
00895                         interface->ipv6_configure->IPv6_ND_state = IPV6_ROUTER_SOLICATION;
00896                     }
00897 
00898                     interface->ipv6_configure->ND_TIMER = 1;
00899                     break;
00900 
00901                 case IPV6_GP_CONFIG:
00902                     if (addr_interface_all_address_ready(interface)) {
00903                         interface->global_address_available = true;
00904                         if (interface->lowpan_info & INTERFACE_NWK_BOOTSRAP_ACTIVE) {
00905                             nwk_bootsrap_state_update(ARM_NWK_BOOTSTRAP_READY, interface);
00906                             /* We will need proxy both mode currently future static mode should not need proxy */
00907                             nd_proxy_upstream_interface_register(interface->id, ipv6_interface_route_validate);
00908                         }
00909                     }
00910 
00911                     // Enable RA route and prefix processing for static configuration mode if RA accept always is enabled
00912                     if (interface->ipv6_configure->ipv6_stack_mode == NET_IPV6_BOOTSTRAP_STATIC &&
00913                             interface->ipv6_configure->accept_ra == NET_IPV6_RA_ACCEPT_ALWAYS) {
00914                         icmpv6_recv_ra_routes(interface, true);
00915                         icmpv6_recv_ra_prefixes(interface, true);
00916                     }
00917 
00918                     if (addr->source == ADDR_SOURCE_SLAAC) {
00919                         ipv6_prefix_router_flag_activate(addr->address);
00920                     }
00921                     break;
00922 
00923                 default:
00924                     /* No special action for subsequent addresses after initial bootstrap */
00925                     if (interface->global_address_available && interface->ipv6_configure->temporaryUlaAddressState) {
00926                         if (addr_ipv6_scope(addr->address, interface) == IPV6_SCOPE_GLOBAL) {
00927                             nwk_bootsrap_state_update(ARM_NWK_BOOTSTRAP_READY, interface);
00928                             tr_debug("Learn Real Global Scope");
00929                             interface->ipv6_configure->temporaryUlaAddressState = false;
00930                             /* We will need proxy both mode currently future static mode should not need proxy */
00931                             nd_proxy_upstream_interface_register(interface->id, ipv6_interface_route_validate);
00932                         }
00933                     }
00934                     break;
00935             }
00936             break;
00937 
00938         case ADDR_CALLBACK_PARENT_FULL:
00939         case ADDR_CALLBACK_DAD_FAILED:
00940             switch (interface->ipv6_configure->IPv6_ND_state) {
00941                 case IPV6_LL_CONFIG:
00942                     tr_warn("No Valid LLaddress..Turn OFF Interface and Push DAD Event");
00943                     nwk_bootsrap_state_update(ARM_NWK_DUPLICATE_ADDRESS_DETECTED, interface);
00944                     break;
00945 
00946                 case IPV6_GP_CONFIG:
00947                     if (interface->lowpan_info & INTERFACE_NWK_BOOTSRAP_ACTIVE) {
00948 
00949                     }
00950                     break;
00951 
00952                 default:
00953                     /* No special action for subsequent addresses after initial bootstrap */
00954                     break;
00955             }
00956             break;
00957 
00958         default:
00959             break;
00960     }
00961 }
00962 
00963 void ipv6_interface_slaac_handler(protocol_interface_info_entry_t *cur, const uint8_t *slaacPrefix, uint8_t prefixLen, uint32_t validLifeTime, uint32_t preferredLifeTime)
00964 {
00965     if_address_entry_t *address_entry = icmpv6_slaac_address_add(cur, slaacPrefix, prefixLen, validLifeTime, preferredLifeTime, false, SLAAC_IID_DEFAULT);
00966     if (address_entry) {
00967         address_entry->cb = ipv6_interface_address_cb;
00968         if (cur->ipv6_configure && cur->ipv6_configure->IPv6_ND_state == IPV6_ROUTER_SOLICATION) {
00969             cur->ipv6_configure->IPv6_ND_state = IPV6_GP_CONFIG;
00970         }
00971         // If DAD not enabled address is valid right away
00972         if (cur->ipv6_configure && cur->dup_addr_detect_transmits == 0) {
00973             address_entry->cb(cur, address_entry, ADDR_CALLBACK_DAD_COMPLETE);
00974         }
00975     }
00976 }
00977 
00978 int8_t ipv6_interface_configure_ipv6_bootstrap_set(int8_t interface_id, net_ipv6_mode_e bootstrap_mode, const uint8_t *ipv6_prefix_pointer)
00979 {
00980     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00981     if (!cur) {
00982         return -1;
00983     }
00984 
00985     if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
00986         return -4;
00987     }
00988 
00989     if (cur->nwk_id != IF_IPV6) {
00990         return -1;
00991     }
00992 
00993     switch (bootstrap_mode) {
00994         case NET_IPV6_BOOTSTRAP_STATIC:
00995             memcpy(cur->ipv6_configure->static_prefix64, ipv6_prefix_pointer, 8);
00996         /* fall through */
00997         case NET_IPV6_BOOTSTRAP_AUTONOMOUS:
00998             cur->bootsrap_mode = ARM_NWK_BOOTSRAP_MODE_ETHERNET_ROUTER;
00999             cur->ipv6_configure->ipv6_stack_mode = bootstrap_mode;
01000             break;
01001         default:
01002             break;
01003     }
01004     return 0;
01005 }
01006 
01007 int8_t ipv6_interface_accept_ra(int8_t interface_id, net_ipv6_accept_ra_e accept_ra)
01008 {
01009     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
01010     if (!cur || !cur->ipv6_configure) {
01011         return -1;
01012     }
01013 
01014     cur->ipv6_configure->accept_ra = accept_ra;
01015 
01016     return 0;
01017 }
01018 
01019 #endif