Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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, ðernet_data_conf_cb, ðernet_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
Generated on Tue Jul 12 2022 14:24:32 by
