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.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
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, ð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 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
Generated on Tue Jul 12 2022 13:54:44 by
