Gleb Klochkov / Mbed OS Climatcontroll_Main

Dependencies:   esp8266-driver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers protocol_ipv6.c Source File

protocol_ipv6.c

00001 /*
00002  * Copyright (c) 2012-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 "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/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     if (opt_out) {
00249         opt_out[0] = opt_type;
00250         opt_out[1] = 1;
00251         memcpy(opt_out + 2, cur->mac, 6);
00252     }
00253     return 8;
00254 }
00255 
00256 /* Parse, and return actual size, or 0 if error */
00257 static uint8_t ethernet_llao_parse(protocol_interface_info_entry_t *cur, const uint8_t *opt_in, sockaddr_t *ll_addr_out)
00258 {
00259     (void) cur;
00260     if (opt_in[1] != 1) {
00261         return 0;
00262     }
00263 
00264     ll_addr_out->addr_type  = ADDR_EUI_48 ;
00265     memcpy(ll_addr_out->address , opt_in + 2, 6);
00266 
00267     return 6;
00268 }
00269 
00270 /**
00271  * \fn ethernet_up
00272  *
00273  * \brief Parse IPv6 header received over the Backhaul link
00274  *
00275  */
00276 /* Input: MAC payload received from Ethernet or other link (frame type was IPv6)
00277  *        Buffer destination = MAC destination (if actually was Ethernet)
00278  *        Buffer source = MAC source
00279  * Output: LL broadcast/multicast flags set based on addresses.
00280  *         Sent to IPv6 forwarding up.
00281  */
00282 static buffer_t *ethernet_up(buffer_t *buf)
00283 {
00284     if (buf->dst_sa .addr_type  == ADDR_EUI_48  && (buf->dst_sa .address [0] & 1)) {
00285         if (memcmp(buf->dst_sa .address , (const uint8_t[]) { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, 6) == 0)
00286             buf->options .ll_broadcast_rx  = true;
00287         else {
00288             buf->options .ll_multicast_rx  = true;
00289         }
00290     }
00291     buf->ip_routed_up = true;
00292     buf->info  = (buffer_info_t)(B_DIR_UP | B_FROM_IPV6_TXRX | B_TO_IPV6_FWD);
00293     return buf;
00294 }
00295 
00296 static void ipv6_nd_bootstrap(protocol_interface_info_entry_t *cur)
00297 {
00298     switch (cur->ipv6_configure->IPv6_ND_state) {
00299         case IPV6_LL_CONFIG:
00300             if (addr_interface_set_ll64(cur, ipv6_interface_address_cb) != 0) {
00301                 cur->ipv6_configure->ND_TIMER = 1;
00302             }
00303             break;
00304 
00305         case IPV6_ROUTER_SOLICATION:
00306             tr_debug("Waiting for ICMPv6 Router Advertisement");
00307             if (ipv6_nd_rs(cur)) {
00308                 if (cur->ipv6_configure->routerSolicationRetryCounter != ROUTER_SOL_MAX_COUNTER) {
00309                     cur->ipv6_configure->routerSolicationRetryCounter++;
00310                 }
00311                 cur->ipv6_configure->ND_TIMER = (cur->ipv6_configure->routerSolicationRetryCounter * 25);
00312 
00313             } else {
00314                 cur->ipv6_configure->ND_TIMER = 1;
00315             }
00316             break;
00317 
00318         case IPV6_GP_GEN:
00319             if (ipv6_generate_static_gp_setup(cur, false) != 0) {
00320                 cur->ipv6_configure->ND_TIMER = 1;
00321             }
00322             break;
00323         case IPV6_GP_CONFIG:
00324             break;
00325 
00326         case IPV6_DHCPV6_SOLICATION:
00327 //              if(dhcpv6_non_temporal_address_solication(cur) == 0)
00328 //              {
00329 //                  cur->ipv6_configure->ND_TIMER = 0;
00330 //              }
00331 //              else
00332 //              {
00333 //                  cur->ipv6_configure->ND_TIMER = 1;
00334 //              }
00335             break;
00336 
00337         case IPV6_DHCPV6_ADDRESS_REQUEST:
00338             break;
00339         case IPV6_DHCPV6_ADDRESS_REQ_FAIL:
00340             tr_warn("DHCP ADDRESS_REQ_FAIL");
00341             /*XXX Do what here? */
00342             break;
00343 
00344         case IPV6_READY:
00345             break;
00346     }
00347 }
00348 
00349 
00350 void ipv6_prefix_on_link_list_add_by_interface_address_list(protocol_interface_info_entry_t *cur_Ipv6, protocol_interface_info_entry_t *curRegisteredInterface)
00351 {
00352     ns_list_foreach(if_address_entry_t, e, &curRegisteredInterface->ip_addresses) {
00353         if (addr_ipv6_scope(e->address,curRegisteredInterface) == IPV6_SCOPE_GLOBAL) {
00354             ipv6_stack_prefix_on_link_update(cur_Ipv6, e->address);
00355         }
00356     }
00357 }
00358 
00359 static void ipv6_stack_prefix_on_link_update(protocol_interface_info_entry_t *cur, uint8_t *address)
00360 {
00361     if (!cur->global_address_available) {
00362         return;
00363     }
00364 
00365     if (addr_interface_gp_prefix_compare(cur, address) != 0) {
00366         ipv6_interface_prefix_on_link_t *new_entry = 0;
00367         ns_list_foreach(ipv6_interface_prefix_on_link_t, tmp_prefix, &prefix_on_link) {
00368             if (memcmp(tmp_prefix->prefix, address, 8) == 0) {
00369                 return;
00370             }
00371         }
00372 
00373         new_entry = ns_dyn_mem_alloc(sizeof(ipv6_interface_prefix_on_link_t));
00374         if (new_entry) {
00375             memset(new_entry->prefix, 0, 16);
00376             memcpy(new_entry->prefix, address, 8);
00377 
00378             new_entry->prefix_len = 64;
00379             // Treat the prefix like a "route", so 3 * advert interval, not 30 days
00380             new_entry->prefix_valid_ttl = (UINT32_C(3) * icmpv6_radv_max_rtr_adv_interval(cur)) / 10;
00381             ns_list_add_to_end(&prefix_on_link, new_entry);
00382             icmpv6_restart_router_advertisements(cur, ADDR_UNSPECIFIED);
00383         }
00384     }
00385 }
00386 
00387 void ipv6_stack_route_advert_update(uint8_t *address, uint8_t prefixLength, uint8_t routePrefer)
00388 {
00389     protocol_interface_info_entry_t *cur = nwk_interface_get_ipv6_ptr();
00390     if (!cur) {
00391         return;
00392     }
00393     if (cur->ipv6_configure->ipv6_stack_mode != NET_IPV6_BOOTSTRAP_STATIC) {
00394         return;
00395     }
00396 
00397 
00398 
00399     if (addr_interface_gp_prefix_compare(cur, address) != 0) {
00400         ns_list_foreach(ipv6_interface_route_on_link_t, cur_prefix, &route_on_link) {
00401             if ((cur_prefix->prefix_len == prefixLength) && bitsequal(cur_prefix->prefix, address, prefixLength)) {
00402                 cur_prefix->routePrefer = routePrefer;
00403                 return;
00404             }
00405         }
00406     }
00407 
00408     ipv6_interface_route_on_link_t *new_entry = ns_dyn_mem_alloc(sizeof(ipv6_interface_route_on_link_t));
00409     if (new_entry) {
00410         memset(new_entry->prefix, 0, 16);
00411         memcpy(new_entry->prefix, address, 16);
00412 
00413         new_entry->prefix_len = prefixLength;
00414         new_entry->routePrefer = routePrefer;
00415         // Treat the prefix like a "route", so 3 * advert interval, not 30 days
00416         new_entry->prefix_valid_ttl = (UINT32_C(3) * icmpv6_radv_max_rtr_adv_interval(cur)) / 10;
00417         ns_list_add_to_end(&route_on_link, new_entry);
00418         icmpv6_restart_router_advertisements(cur, ADDR_UNSPECIFIED);
00419     }
00420 }
00421 
00422 void ipv6_prefix_on_link_update(uint8_t *address)
00423 {
00424     protocol_interface_info_entry_t *cur = nwk_interface_get_ipv6_ptr();
00425     if (cur) {
00426         //Call IPv6 Onlink Update
00427         if (cur->ipv6_configure->ipv6_stack_mode == NET_IPV6_BOOTSTRAP_STATIC) {
00428             ipv6_stack_prefix_on_link_update(cur, address);
00429         }
00430     }
00431 }
00432 
00433 static void ipv6_stack_prefix_on_link_remove(protocol_interface_info_entry_t *cur, uint8_t *address)
00434 {
00435     ns_list_foreach(ipv6_interface_prefix_on_link_t, cur_prefix, &prefix_on_link) {
00436         if (memcmp(cur_prefix->prefix, address, 8) == 0) {
00437             cur_prefix->prefix_valid_ttl = 0;
00438             icmpv6_restart_router_advertisements(cur, ADDR_UNSPECIFIED);
00439             break;
00440         }
00441     }
00442 }
00443 
00444 void ipv6_prefix_on_link_remove(uint8_t *address)
00445 {
00446     protocol_interface_info_entry_t *cur = nwk_interface_get_ipv6_ptr();
00447     if (cur) {
00448         if (cur->ipv6_configure->ipv6_stack_mode == NET_IPV6_BOOTSTRAP_STATIC) {
00449             ipv6_stack_prefix_on_link_remove(cur, address);
00450         }
00451     }
00452 }
00453 
00454 void ipv6_stack_route_advert_remove(uint8_t *address, uint8_t prefixLength)
00455 {
00456     protocol_interface_info_entry_t *cur = nwk_interface_get_ipv6_ptr();
00457     if (!cur) {
00458         return;
00459     }
00460     if (cur->ipv6_configure->ipv6_stack_mode == NET_IPV6_BOOTSTRAP_STATIC) {
00461         ns_list_foreach(ipv6_interface_route_on_link_t, cur_prefix, &route_on_link)
00462         {
00463             if ((cur_prefix->prefix_len == prefixLength) && bitsequal(cur_prefix->prefix, address, prefixLength)) {
00464                 cur_prefix->prefix_valid_ttl = 0;
00465                 icmpv6_restart_router_advertisements(cur, ADDR_UNSPECIFIED);
00466                 break;
00467             }
00468         }
00469     }
00470 }
00471 
00472 void ipv6_prefix_online_list_free(void)
00473 {
00474     ns_list_foreach_safe(ipv6_interface_prefix_on_link_t, cur, &prefix_on_link) {
00475         ns_list_remove(&prefix_on_link, cur);
00476         ns_dyn_mem_free(cur);
00477     }
00478 }
00479 
00480 void ipv6_rote_advert_list_free(void)
00481 {
00482     ns_list_foreach_safe(ipv6_interface_route_on_link_t, cur, &route_on_link) {
00483         ns_list_remove(&route_on_link, cur);
00484         ns_dyn_mem_free(cur);
00485     }
00486 }
00487 
00488 void ipv6_core_slow_timer_event_handle(struct protocol_interface_info_entry *cur)
00489 {
00490     if (cur->ipv6_configure) {
00491         protocol_interface_info_entry_t *curRegisteredInterface;
00492         if (cur->ipv6_configure->wb_table_ttl-- == 1) {
00493             //tr_debug("WB Table TTL");
00494             whiteboard_ttl_update(WB_UPDATE_PERIOD_SECONDS);
00495             cur->ipv6_configure->wb_table_ttl   = WB_UPDATE_PERIOD_SECONDS;
00496         }
00497 
00498         if (cur->ipv6_configure->ipv6_stack_mode == NET_IPV6_BOOTSTRAP_STATIC) {
00499 
00500             if (cur->global_address_available) {
00501                 curRegisteredInterface = protocol_stack_interface_info_get(IF_6LoWPAN);
00502                 if (curRegisteredInterface) {
00503 
00504                     ipv6_prefix_on_link_list_add_by_interface_address_list(cur, curRegisteredInterface);
00505                 }
00506             }
00507         }
00508     }
00509 }
00510 
00511 void ipv6_core_timer_event_handle(protocol_interface_info_entry_t *cur, const uint8_t event)
00512 {
00513     (void)event;
00514     if (cur->ipv6_configure->ND_TIMER) {
00515         if (cur->ipv6_configure->ND_TIMER-- == 1) {
00516             //Call ND State Machine
00517             ipv6_nd_bootstrap(cur);
00518         }
00519     }
00520 }
00521 
00522 int ipv6_prefix_register(uint8_t *prefix_64, uint32_t lifetime, uint32_t prefer_lifetime)
00523 {
00524     prefix_entry_t *new_entry = icmpv6_prefix_add(&ipv6_prefixs, prefix_64, 64, lifetime, prefer_lifetime, (PIO_L | PIO_A));
00525     if (new_entry) {
00526         memset(&new_entry->prefix[8], 0, 8);
00527         new_entry->options = PIO_L | PIO_A;
00528         return 0;
00529     }
00530     return -1;
00531 }
00532 
00533 int ipv6_interface_route_validate(int8_t interface_id , uint8_t *address)
00534 {
00535     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00536     if (!cur) {
00537         return -1;
00538     } else if (!cur->ipv6_configure) {
00539         return -1;
00540     } else if (cur->ipv6_configure->IPv6_ND_state != IPV6_READY) {
00541         return -1;
00542     }
00543 
00544     //Validate route OnLink
00545     ipv6_route_t *route;
00546     route = ipv6_route_choose_next_hop(address, interface_id, NULL);
00547 
00548     //Respond default route only when we have other interface for route
00549     if (route && route->on_link) {
00550         return 0;
00551     }
00552 
00553     return -1;
00554 
00555 }
00556 
00557 int8_t ipv6_interface_up(protocol_interface_info_entry_t *cur)
00558 {
00559     uint8_t ipv6_interface_adr[16];
00560 
00561     if (cur->if_stack_buffer_handler) {
00562         return -1;
00563     }
00564 
00565     if (cur->ipv6_configure->ipv6_stack_mode == NET_IPV6_BOOTSTRAP_STATIC) {
00566         uint32_t lifeTime, prefLifetime;
00567         uint8_t pre_options;
00568         memcpy(&ipv6_interface_adr[0], cur->ipv6_configure->static_prefix64, 8);
00569         memcpy(&ipv6_interface_adr[8], cur->iid_eui64, 8);
00570         prefix_entry_t *new_entry = 0;
00571         // Treat the prefix like a "route", so 3 * advert interval, not 30 days
00572         lifeTime = (UINT32_C(3) * icmpv6_radv_max_rtr_adv_interval(cur)) / 10;
00573         prefLifetime = lifeTime / 2;
00574         pre_options = PIO_L | PIO_A | PIO_R;
00575 
00576         new_entry = icmpv6_prefix_add(&ipv6_prefixs, ipv6_interface_adr, 64, lifeTime, prefLifetime, pre_options);
00577 
00578         if (!new_entry) {
00579             return -1;
00580         }
00581         memcpy(&new_entry->prefix[8], &ipv6_interface_adr[8], 8);
00582         new_entry->options = pre_options;
00583 
00584         ipv6_route_add(ipv6_interface_adr, 64, cur->id, NULL, ROUTE_STATIC, 0xffffffff, 1);
00585 
00586         // Disable RA route and prefix processing until static address has been added to interface
00587         icmpv6_recv_ra_routes(cur, false);
00588         icmpv6_recv_ra_prefixes(cur, false);
00589     }
00590 
00591     cur->ipv6_configure->IPv6_ND_state = IPV6_LL_CONFIG;
00592     cur->ipv6_configure->ND_TIMER = 1;
00593 
00594     cur->ipv6_configure->routerSolicationRetryCounter = 0;
00595     cur->ipv6_configure->wb_table_ttl       = WB_UPDATE_PERIOD_SECONDS;
00596     icmpv6_radv_disable(cur);
00597 
00598     tr_debug("IPV6 interface Base Ready");
00599     cur->if_stack_buffer_handler = ipv6_stack;
00600     cur->if_llao_write = ethernet_llao_write;
00601     cur->if_llao_parse = ethernet_llao_parse;
00602     cur->ipv6_neighbour_cache.max_ll_len = 6;
00603     cur->ipv6_neighbour_cache.link_mtu = cur->max_link_mtu = 1500;
00604     cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ACTIVE;
00605     cur->lowpan_info |= INTERFACE_NWK_ACTIVE;
00606 
00607     // Always want fe80::/64 to be an on-link prefix.
00608     ipv6_route_add(ADDR_LINK_LOCAL_PREFIX, 64, cur->id, NULL, ROUTE_STATIC, 0xFFFFFFFF, 0);
00609 
00610     // Putting a multicast route to ff00::/8 makes sure we can always transmit multicast.
00611     // Interface metric will determine which interface is actually used, if we have multiple.
00612     ipv6_route_add(ADDR_LINK_LOCAL_ALL_NODES, 8, cur->id, NULL, ROUTE_STATIC, 0xFFFFFFFF, -1);
00613 
00614     return 0;
00615 }
00616 
00617 int8_t ipv6_interface_down(protocol_interface_info_entry_t *cur)
00618 {
00619     if (!cur || !(cur->lowpan_info & INTERFACE_NWK_ACTIVE)) {
00620         return -1;
00621     }
00622 
00623     whiteboard_interface_unregister_all_address(cur->id);
00624     icmpv6_prefix_list_free(&ipv6_prefixs);
00625     ipv6_prefix_online_list_free();
00626     ipv6_rote_advert_list_free();
00627     neighbor_cache_flush(&cur->neigh_cache);
00628     ipv6_route_table_remove_interface(cur->id);
00629     protocol_core_interface_info_reset(cur);
00630     cur->ipv6_configure->wb_table_ttl = 0;
00631     cur->lowpan_info &= ~INTERFACE_NWK_ACTIVE;
00632     cur->global_address_available = false;
00633     //Clear all generated proxies
00634     nd_proxy_upstream_interface_unregister(cur->id);
00635 
00636     return 0;
00637 }
00638 
00639 
00640 static uint8_t ipv6_nd_rs(protocol_interface_info_entry_t *cur)
00641 {
00642     buffer_t *buf = icmpv6_build_rs(cur, NULL);
00643     if (buf) {
00644         tr_debug("Push RS to IPV6");
00645         arm_net_protocol_packet_handler(buf, cur);
00646         return 1;
00647     }
00648     return 0;
00649 }
00650 
00651 #ifdef RADV_TX
00652 void ipv6_nd_ra_advert(protocol_interface_info_entry_t *cur, const uint8_t *dest)
00653 {
00654     /* 12 base size, plus allow 8 for MTU and 16 for SLLA */
00655     uint16_t length = 12 + 8 + 16;
00656     length += 32 * ns_list_count(&ipv6_prefixs);
00657     length += 32 * ns_list_count(&prefix_on_link);
00658 
00659     ns_list_foreach(ipv6_interface_route_on_link_t, tmp_route, &route_on_link) {
00660         if (tmp_route->prefix_len < 65) {
00661             length += 16;    // add upper 64-bit
00662         } else {
00663             length += 24;    // add full address
00664         }
00665     }
00666 
00667     buffer_t *buf = buffer_get(length);
00668     if (buf) {
00669         uint8_t *ptr = buffer_data_pointer(buf);
00670 
00671         buf->options .hop_limit  = 255;
00672         buf->options .type  = ICMPV6_TYPE_INFO_RA;
00673         buf->options .code  = 0x00;
00674         *ptr++ = cur->adv_cur_hop_limit;
00675         *ptr++ = cur->rtr_adv_flags;
00676         //Do not advertise default route: set Router Lifetime to 0
00677         ptr = common_write_16_bit(0, ptr);
00678         ptr = common_write_32_bit(cur->adv_reachable_time, ptr);
00679         ptr = common_write_32_bit(cur->adv_retrans_timer, ptr);
00680 
00681         // We don't include our Source Link-Layer address - we're not
00682         // advertising routes, so we don't expect anyone to be talking directly
00683         // to us; we're just acting as an ND proxy. If we put in the SLLAO, we
00684         // add ourselves to their Neighbour Cache unnecessarily. This can be
00685         // reactivated if we start advertising actual routes
00686 #if 0
00687         // Set the source Link-Layer address
00688         ptr = icmpv6_write_icmp_lla(cur, ptr, ICMPV6_OPT_SRC_LL_ADDR);
00689 #endif
00690 
00691         //MTU
00692         if (cur->adv_link_mtu != 0) {
00693             ptr = icmpv6_write_mtu_option(cur->adv_link_mtu, ptr);
00694         }
00695 
00696         //IPv6 Prefixes
00697         ptr = icmpv6_write_prefix_option(&ipv6_prefixs,  ptr, 0, cur);
00698 
00699         // Update our own routing table prefixes in sync with what we're advertising above
00700         ns_list_foreach(prefix_entry_t, pfx, &ipv6_prefixs) {
00701             if (pfx->options & PIO_L) {
00702                 ipv6_route_add(pfx->prefix, pfx->prefix_len, cur->id, NULL, ROUTE_STATIC, pfx->lifetime, 1);
00703             }
00704         }
00705 
00706         ns_list_foreach_safe(ipv6_interface_prefix_on_link_t, pfx, &prefix_on_link) {
00707             ipv6_route_add(pfx->prefix, pfx->prefix_len, cur->id, NULL, ROUTE_STATIC, pfx->prefix_valid_ttl, 0);
00708 
00709             *ptr++ = ICMPV6_OPT_PREFIX_INFO;
00710             *ptr++ = 4; // length
00711             *ptr++ = pfx->prefix_len;
00712             *ptr++ = PIO_L;
00713             ptr = common_write_32_bit(pfx->prefix_valid_ttl, ptr); // Valid Lifetime
00714             ptr = common_write_32_bit(pfx->prefix_valid_ttl >> 1, ptr); // Preferred Lifetime
00715             ptr = common_write_32_bit(0, ptr);
00716             memcpy(ptr, pfx->prefix, 16);
00717             ptr += 16;
00718             if (pfx->prefix_valid_ttl == 0) {
00719                 ns_list_remove(&prefix_on_link, pfx);
00720                 ns_dyn_mem_free(pfx);
00721             }
00722         }
00723 
00724         ns_list_foreach_safe(ipv6_interface_route_on_link_t, tmp_route, &route_on_link) {
00725             uint8_t prefix_bytes;
00726             *ptr++ = ICMPV6_OPT_ROUTE_INFO;
00727             if (tmp_route->prefix_len < 65) {
00728                 *ptr++ = 2;
00729                 prefix_bytes = 8;
00730             } else {
00731                 *ptr++ = 3;
00732                 prefix_bytes = 16;
00733             }
00734             *ptr++ = tmp_route->prefix_len;
00735             *ptr++ = tmp_route->routePrefer;
00736             ptr = common_write_32_bit(tmp_route->prefix_valid_ttl, ptr);
00737             memcpy(ptr, tmp_route->prefix, prefix_bytes);
00738             ptr += prefix_bytes;
00739 
00740             if (tmp_route->prefix_valid_ttl == 0) {
00741                 ns_list_remove(&route_on_link, tmp_route);
00742                 ns_dyn_mem_free(tmp_route);
00743             }
00744         }
00745 
00746         buffer_data_end_set(buf, ptr);
00747         memcpy(buf->dst_sa .address , dest, 16);
00748         /* Source must be LL address (even if non-LL dest) */
00749         if (addr_interface_get_ll_address(cur, buf->src_sa .address , 0)) {
00750             tr_debug("No address defined");
00751             buffer_free(buf);
00752             return;
00753         }
00754         buf->dst_sa .addr_type  = ADDR_IPV6 ;
00755         buf->src_sa .addr_type  = ADDR_IPV6 ;
00756 
00757         buf->interface  = cur;
00758         buf->info  = (buffer_info_t)(B_FROM_ICMP | B_TO_ICMP | B_DIR_DOWN);
00759         arm_net_protocol_packet_handler(buf, cur);
00760     }
00761 }
00762 #endif
00763 
00764 static void ipv6_stack(buffer_t *b)
00765 {
00766     /* Protocol Buffer Handle */
00767     int8_t status;
00768     nwk_interface_id nwk_id = IF_IPV6;
00769     if (b) {
00770         //Save Original Interface id
00771         nwk_id = b->interface ->nwk_id;
00772     }
00773     while (b) {
00774         /* Buffer Direction Select Switch */
00775         if ((b->info  & B_DIR_MASK) == B_DIR_DOWN) {
00776             /* Direction DOWN */
00777             switch (b->info  & B_TO_MASK) {
00778                 case B_TO_ICMP:
00779                     /* Build ICMP Header */
00780                     b = icmpv6_down(b);
00781                     break;
00782 
00783                 case B_TO_UDP:
00784                     /* Build UDP Header */
00785                     b = udp_down(b);
00786                     break;
00787 
00788                 case B_TO_IPV6:
00789                     /* Build IP Header */
00790                     b = ipv6_down(b);
00791                     break;
00792 
00793                 case B_TO_IPV6_FWD:
00794                     /* IPv6 forwarding */
00795                     b = ipv6_forwarding_down(b);
00796                     break;
00797 
00798                 case B_TO_IPV6_TXRX:
00799                     /* Resolution, preparing MAC payload */
00800                     b = ethernet_down(b);
00801                     break;
00802 
00803                 case B_TO_MAC:
00804                     b = ethernet_header_build_push(b, ETHERTYPE_IPV6, &status);
00805                     if (b) {
00806                         //GET Interface Pointer
00807                         //uint8_t *ptr = b->buf + b->buf_ptr;
00808                         //uint16_t len = b->buf_end - b->buf_ptr;
00809                         //ethernet_tx(ptr, len);
00810                         if (status == 0) {
00811                             socket_tx_buffer_event_and_free(b, SOCKET_TX_DONE);
00812                         } else {
00813                             socket_tx_buffer_event_and_free(b, SOCKET_TX_FAIL);
00814                         }
00815                     }
00816                     return;
00817 
00818                 default:
00819                     b = buffer_free(b);
00820                     break;
00821             }
00822         } else {
00823             /* Direction UP */
00824             switch (b->info  & B_TO_MASK) {
00825                 case B_TO_APP:
00826                     socket_up(b);
00827                     b = NULL;
00828                     break;
00829 
00830                 case B_TO_MAC:
00831                     /* Beacon and command frames */
00832                     //b = mac_up(b);
00833                     break;
00834 
00835                 case B_TO_ICMP:
00836                     /* Parse ICMP Message */
00837                     b = icmpv6_up(b);
00838                     break;
00839 
00840                 case B_TO_UDP:
00841                     /* Parse UDP Message */
00842                     b = udp_up(b);
00843                     break;
00844 
00845                 case B_TO_IPV6_FWD:
00846                     /* Handle IP Payload */
00847                     b = ipv6_forwarding_up(b);
00848                     break;
00849 
00850                 case B_TO_IPV6_TXRX:
00851                     /* Handle MAC Payload */
00852                     b = ethernet_up(b);
00853                     break;
00854 
00855                 case B_TO_TCP:
00856                     //tr_debug("--> TCP_up()");
00857                     b = tcp_up(b);
00858                     break;
00859 
00860                 default:
00861                     tr_debug("LLL");
00862                     b = buffer_free(b);
00863                     break;
00864             }
00865         }
00866 
00867         if (b) {
00868             //Check If Stack forward packet to different interface
00869             if (b->interface ->nwk_id != nwk_id) {
00870                 protocol_push(b);
00871                 b = 0;
00872             }
00873         }
00874     }
00875 }
00876 
00877 static void ipv6_interface_address_cb(protocol_interface_info_entry_t *interface, if_address_entry_t *addr, if_address_callback_t reason)
00878 {
00879     tr_debug("Interface ID: %i, ipv6: %s", interface->id, trace_ipv6(addr->address));
00880 
00881     switch (reason) {
00882         case ADDR_CALLBACK_DAD_COMPLETE:
00883             tr_debug("DAD OK");
00884             switch (interface->ipv6_configure->IPv6_ND_state) {
00885                 case IPV6_LL_CONFIG:
00886                     if (interface->ipv6_configure->ipv6_stack_mode == NET_IPV6_BOOTSTRAP_STATIC) {
00887                         interface->ipv6_configure->IPv6_ND_state = IPV6_GP_GEN;
00888                     } else {
00889                         interface->ipv6_configure->IPv6_ND_state = IPV6_ROUTER_SOLICATION;
00890                     }
00891 
00892                     interface->ipv6_configure->ND_TIMER = 1;
00893                     break;
00894 
00895                 case IPV6_GP_CONFIG:
00896                     if (addr_interface_all_address_ready(interface)) {
00897                         interface->global_address_available = true;
00898                         if (interface->lowpan_info & INTERFACE_NWK_BOOTSRAP_ACTIVE) {
00899                             nwk_bootsrap_state_update(ARM_NWK_BOOTSTRAP_READY, interface);
00900                             /* We will need proxy both mode currently future static mode should not need proxy */
00901                             nd_proxy_upstream_interface_register(interface->id, ipv6_interface_route_validate);
00902                         }
00903                     }
00904 
00905                     // Enable RA route and prefix processing for static configuration mode if RA accept always is enabled
00906                     if (interface->ipv6_configure->ipv6_stack_mode == NET_IPV6_BOOTSTRAP_STATIC &&
00907                         interface->ipv6_configure->accept_ra == NET_IPV6_RA_ACCEPT_ALWAYS) {
00908                         icmpv6_recv_ra_routes(interface, true);
00909                         icmpv6_recv_ra_prefixes(interface, true);
00910                     }
00911 
00912                     if (addr->source == ADDR_SOURCE_SLAAC) {
00913                         ipv6_prefix_router_flag_activate(addr->address);
00914                     }
00915                     break;
00916 
00917                 default:
00918                     /* No special action for subsequent addresses after initial bootstrap */
00919                     if (interface->global_address_available && interface->ipv6_configure->temporaryUlaAddressState) {
00920                         if (addr_ipv6_scope(addr->address,interface) == IPV6_SCOPE_GLOBAL) {
00921                             nwk_bootsrap_state_update(ARM_NWK_BOOTSTRAP_READY, interface);
00922                             tr_debug("Learn Real Global Scope");
00923                             interface->ipv6_configure->temporaryUlaAddressState = false;
00924                             /* We will need proxy both mode currently future static mode should not need proxy */
00925                             nd_proxy_upstream_interface_register(interface->id, ipv6_interface_route_validate);
00926                         }
00927                     }
00928                     break;
00929             }
00930             break;
00931 
00932         case ADDR_CALLBACK_PARENT_FULL:
00933         case ADDR_CALLBACK_DAD_FAILED:
00934             switch (interface->ipv6_configure->IPv6_ND_state) {
00935                 case IPV6_LL_CONFIG:
00936                     tr_warn("No Valid LLaddress..Turn OFF Interface and Push DAD Event");
00937                     nwk_bootsrap_state_update(ARM_NWK_DUPLICATE_ADDRESS_DETECTED, interface);
00938                     break;
00939 
00940                 case IPV6_GP_CONFIG:
00941                     if (interface->lowpan_info & INTERFACE_NWK_BOOTSRAP_ACTIVE) {
00942 
00943                     }
00944                     break;
00945 
00946                 default:
00947                     /* No special action for subsequent addresses after initial bootstrap */
00948                     break;
00949             }
00950             break;
00951 
00952         default:
00953             break;
00954     }
00955 }
00956 
00957 void ipv6_interface_slaac_handler(protocol_interface_info_entry_t *cur, uint8_t *slaacPrefix, uint8_t prefixLen, uint32_t validLifeTime, uint32_t preferredLifeTime)
00958 {
00959     if_address_entry_t *address_entry = icmpv6_slaac_address_add(cur, slaacPrefix, prefixLen, validLifeTime, preferredLifeTime, false, SLAAC_IID_DEFAULT);
00960     if (address_entry) {
00961         address_entry->cb = ipv6_interface_address_cb;
00962         if (cur->ipv6_configure && cur->ipv6_configure->IPv6_ND_state == IPV6_ROUTER_SOLICATION) {
00963             cur->ipv6_configure->IPv6_ND_state = IPV6_GP_CONFIG;
00964         }
00965     }
00966 }
00967 
00968 int8_t ipv6_interface_configure_ipv6_bootstrap_set(int8_t interface_id, net_ipv6_mode_e bootstrap_mode, const uint8_t *ipv6_prefix_pointer)
00969 {
00970     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00971     if (!cur) {
00972         return -1;
00973     }
00974 
00975     if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
00976         return -4;
00977     }
00978 
00979     if (cur->nwk_id != IF_IPV6) {
00980         return -1;
00981     }
00982 
00983     switch (bootstrap_mode) {
00984         case NET_IPV6_BOOTSTRAP_STATIC:
00985             memcpy(cur->ipv6_configure->static_prefix64, ipv6_prefix_pointer, 8);
00986             /* fall through */
00987         case NET_IPV6_BOOTSTRAP_AUTONOMOUS:
00988             cur->bootsrap_mode = ARM_NWK_BOOTSRAP_MODE_ETHERNET_ROUTER;
00989             cur->ipv6_configure->ipv6_stack_mode = bootstrap_mode;
00990             break;
00991         default:
00992             break;
00993     }
00994     return 0;
00995 }
00996 
00997 int8_t ipv6_interface_accept_ra(int8_t interface_id, net_ipv6_accept_ra_e accept_ra)
00998 {
00999     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
01000     if (!cur || !cur->ipv6_configure) {
01001         return -1;
01002     }
01003 
01004     cur->ipv6_configure->accept_ra = accept_ra;
01005 
01006     return 0;
01007 }
01008 
01009 #endif