1/** 2 * @file 3 * 4 * Neighbor discovery and stateless address autoconfiguration for IPv6. 5 * Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862 6 * (Address autoconfiguration). 7 */ 8 9/* 10 * Copyright (c) 2010 Inico Technologies Ltd. 11 * All rights reserved. 12 * 13 * Redistribution and use in source and binary forms, with or without modification, 14 * are permitted provided that the following conditions are met: 15 * 16 * 1. Redistributions of source code must retain the above copyright notice, 17 * this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright notice, 19 * this list of conditions and the following disclaimer in the documentation 20 * and/or other materials provided with the distribution. 21 * 3. The name of the author may not be used to endorse or promote products 22 * derived from this software without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 25 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 27 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 29 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 32 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 33 * OF SUCH DAMAGE. 34 * 35 * This file is part of the lwIP TCP/IP stack. 36 * 37 * Author: Ivan Delamer <delamer@inicotech.com> 38 * 39 * 40 * Please coordinate changes and requests with Ivan Delamer 41 * <delamer@inicotech.com> 42 */ 43 44#include "lwip/opt.h" 45 46#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ 47 48#include "lwip/nd6.h" 49#include "lwip/priv/nd6_priv.h" 50#include "lwip/prot/nd6.h" 51#include "lwip/prot/icmp6.h" 52#include "lwip/pbuf.h" 53#include "lwip/mem.h" 54#include "lwip/memp.h" 55#include "lwip/ip6.h" 56#include "lwip/ip6_addr.h" 57#include "lwip/inet_chksum.h" 58#include "lwip/netif.h" 59#include "lwip/icmp6.h" 60#include "lwip/mld6.h" 61#include "lwip/ip.h" 62#include "lwip/stats.h" 63#include "lwip/dns.h" 64 65#include <string.h> 66 67#ifdef LWIP_HOOK_FILENAME 68#include LWIP_HOOK_FILENAME 69#endif 70 71#if LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK 72#error LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK 73#endif 74 75/* Router tables. */ 76struct nd6_neighbor_cache_entry neighbor_cache[LWIP_ND6_NUM_NEIGHBORS]; 77struct nd6_destination_cache_entry destination_cache[LWIP_ND6_NUM_DESTINATIONS]; 78struct nd6_prefix_list_entry prefix_list[LWIP_ND6_NUM_PREFIXES]; 79struct nd6_router_list_entry default_router_list[LWIP_ND6_NUM_ROUTERS]; 80 81/* Default values, can be updated by a RA message. */ 82u32_t reachable_time = LWIP_ND6_REACHABLE_TIME; 83u32_t retrans_timer = LWIP_ND6_RETRANS_TIMER; /* @todo implement this value in timer */ 84 85/* Index for cache entries. */ 86static u8_t nd6_cached_neighbor_index; 87static u8_t nd6_cached_destination_index; 88 89/* Multicast address holder. */ 90static ip6_addr_t multicast_address; 91 92/* Static buffer to parse RA packet options (size of a prefix option, biggest option) */ 93static u8_t nd6_ra_buffer[sizeof(struct prefix_option)]; 94 95/* Forward declarations. */ 96static s8_t nd6_find_neighbor_cache_entry(const ip6_addr_t *ip6addr); 97static s8_t nd6_new_neighbor_cache_entry(void); 98static void nd6_free_neighbor_cache_entry(s8_t i); 99static s8_t nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr); 100static s8_t nd6_new_destination_cache_entry(void); 101static s8_t nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif); 102static s8_t nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif); 103static s8_t nd6_get_router(const ip6_addr_t *router_addr, struct netif *netif); 104static s8_t nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif); 105static s8_t nd6_get_onlink_prefix(ip6_addr_t *prefix, struct netif *netif); 106static s8_t nd6_new_onlink_prefix(ip6_addr_t *prefix, struct netif *netif); 107static s8_t nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif); 108static err_t nd6_queue_packet(s8_t neighbor_index, struct pbuf *q); 109 110#define ND6_SEND_FLAG_MULTICAST_DEST 0x01 111#define ND6_SEND_FLAG_ALLNODES_DEST 0x02 112static void nd6_send_ns(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags); 113static void nd6_send_na(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags); 114static void nd6_send_neighbor_cache_probe(struct nd6_neighbor_cache_entry *entry, u8_t flags); 115#if LWIP_IPV6_SEND_ROUTER_SOLICIT 116static err_t nd6_send_rs(struct netif *netif); 117#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ 118 119#if LWIP_ND6_QUEUEING 120static void nd6_free_q(struct nd6_q_entry *q); 121#else /* LWIP_ND6_QUEUEING */ 122#define nd6_free_q(q) pbuf_free(q) 123#endif /* LWIP_ND6_QUEUEING */ 124static void nd6_send_q(s8_t i); 125 126 127/** 128 * Process an incoming neighbor discovery message 129 * 130 * @param p the nd packet, p->payload pointing to the icmpv6 header 131 * @param inp the netif on which this packet was received 132 */ 133void 134nd6_input(struct pbuf *p, struct netif *inp) 135{ 136 u8_t msg_type; 137 s8_t i; 138 139 ND6_STATS_INC(nd6.recv); 140 141 msg_type = *((u8_t *)p->payload); 142 switch (msg_type) { 143 case ICMP6_TYPE_NA: /* Neighbor Advertisement. */ 144 { 145 struct na_header *na_hdr; 146 struct lladdr_option *lladdr_opt; 147 148 /* Check that na header fits in packet. */ 149 if (p->len < (sizeof(struct na_header))) { 150 /* @todo debug message */ 151 pbuf_free(p); 152 ND6_STATS_INC(nd6.lenerr); 153 ND6_STATS_INC(nd6.drop); 154 return; 155 } 156 157 na_hdr = (struct na_header *)p->payload; 158 159 /* Unsolicited NA?*/ 160 if (ip6_addr_ismulticast(ip6_current_dest_addr())) { 161 ip6_addr_t target_address; 162 163 /* This is an unsolicited NA. 164 * link-layer changed? 165 * part of DAD mechanism? */ 166 167 /* Create an aligned copy. */ 168 ip6_addr_set(&target_address, &(na_hdr->target_address)); 169 170#if LWIP_IPV6_DUP_DETECT_ATTEMPTS 171 /* If the target address matches this netif, it is a DAD response. */ 172 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 173 if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) && 174 ip6_addr_cmp(&target_address, netif_ip6_addr(inp, i))) { 175 /* We are using a duplicate address. */ 176 netif_ip6_addr_set_state(inp, i, IP6_ADDR_INVALID); 177 178#if LWIP_IPV6_AUTOCONFIG 179 /* Check to see if this address was autoconfigured. */ 180 if (!ip6_addr_islinklocal(&target_address)) { 181 i = nd6_get_onlink_prefix(&target_address, inp); 182 if (i >= 0) { 183 /* Mark this prefix as duplicate, so that we don't use it 184 * to generate this address again. */ 185 prefix_list[i].flags |= ND6_PREFIX_AUTOCONFIG_ADDRESS_DUPLICATE; 186 } 187 } 188#endif /* LWIP_IPV6_AUTOCONFIG */ 189 190 pbuf_free(p); 191 return; 192 } 193 } 194#endif /* LWIP_IPV6_DUP_DETECT_ATTEMPTS */ 195 196 /* Check that link-layer address option also fits in packet. */ 197 if (p->len < (sizeof(struct na_header) + 2)) { 198 /* @todo debug message */ 199 pbuf_free(p); 200 ND6_STATS_INC(nd6.lenerr); 201 ND6_STATS_INC(nd6.drop); 202 return; 203 } 204 205 lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); 206 207 if (p->len < (sizeof(struct na_header) + (lladdr_opt->length << 3))) { 208 /* @todo debug message */ 209 pbuf_free(p); 210 ND6_STATS_INC(nd6.lenerr); 211 ND6_STATS_INC(nd6.drop); 212 return; 213 } 214 215 /* This is an unsolicited NA, most likely there was a LLADDR change. */ 216 i = nd6_find_neighbor_cache_entry(&target_address); 217 if (i >= 0) { 218 if (na_hdr->flags & ND6_FLAG_OVERRIDE) { 219 MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); 220 } 221 } 222 } else { 223 ip6_addr_t target_address; 224 225 /* This is a solicited NA. 226 * neighbor address resolution response? 227 * neighbor unreachability detection response? */ 228 229 /* Create an aligned copy. */ 230 ip6_addr_set(&target_address, &(na_hdr->target_address)); 231 232 /* Find the cache entry corresponding to this na. */ 233 i = nd6_find_neighbor_cache_entry(&target_address); 234 if (i < 0) { 235 /* We no longer care about this target address. drop it. */ 236 pbuf_free(p); 237 return; 238 } 239 240 /* Update cache entry. */ 241 if ((na_hdr->flags & ND6_FLAG_OVERRIDE) || 242 (neighbor_cache[i].state == ND6_INCOMPLETE)) { 243 /* Check that link-layer address option also fits in packet. */ 244 if (p->len < (sizeof(struct na_header) + 2)) { 245 /* @todo debug message */ 246 pbuf_free(p); 247 ND6_STATS_INC(nd6.lenerr); 248 ND6_STATS_INC(nd6.drop); 249 return; 250 } 251 252 lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); 253 254 if (p->len < (sizeof(struct na_header) + (lladdr_opt->length << 3))) { 255 /* @todo debug message */ 256 pbuf_free(p); 257 ND6_STATS_INC(nd6.lenerr); 258 ND6_STATS_INC(nd6.drop); 259 return; 260 } 261 262 MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); 263 } 264 265 neighbor_cache[i].netif = inp; 266 neighbor_cache[i].state = ND6_REACHABLE; 267 neighbor_cache[i].counter.reachable_time = reachable_time; 268 269 /* Send queued packets, if any. */ 270 if (neighbor_cache[i].q != NULL) { 271 nd6_send_q(i); 272 } 273 } 274 275 break; /* ICMP6_TYPE_NA */ 276 } 277 case ICMP6_TYPE_NS: /* Neighbor solicitation. */ 278 { 279 struct ns_header *ns_hdr; 280 struct lladdr_option *lladdr_opt; 281 u8_t accepted; 282 283 /* Check that ns header fits in packet. */ 284 if (p->len < sizeof(struct ns_header)) { 285 /* @todo debug message */ 286 pbuf_free(p); 287 ND6_STATS_INC(nd6.lenerr); 288 ND6_STATS_INC(nd6.drop); 289 return; 290 } 291 292 ns_hdr = (struct ns_header *)p->payload; 293 294 /* Check if there is a link-layer address provided. Only point to it if in this buffer. */ 295 if (p->len >= (sizeof(struct ns_header) + 2)) { 296 lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct ns_header)); 297 if (p->len < (sizeof(struct ns_header) + (lladdr_opt->length << 3))) { 298 lladdr_opt = NULL; 299 } 300 } else { 301 lladdr_opt = NULL; 302 } 303 304 /* Check if the target address is configured on the receiving netif. */ 305 accepted = 0; 306 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { 307 if ((ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) || 308 (ip6_addr_istentative(netif_ip6_addr_state(inp, i)) && 309 ip6_addr_isany(ip6_current_src_addr()))) && 310 ip6_addr_cmp(&(ns_hdr->target_address), netif_ip6_addr(inp, i))) { 311 accepted = 1; 312 break; 313 } 314 } 315 316 /* NS not for us? */ 317 if (!accepted) { 318 pbuf_free(p); 319 return; 320 } 321 322 /* Check for ANY address in src (DAD algorithm). */ 323 if (ip6_addr_isany(ip6_current_src_addr())) { 324 /* Sender is validating this address. */ 325 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { 326 if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) && 327 ip6_addr_cmp(&(ns_hdr->target_address), netif_ip6_addr(inp, i))) { 328 /* Send a NA back so that the sender does not use this address. */ 329 nd6_send_na(inp, netif_ip6_addr(inp, i), ND6_FLAG_OVERRIDE | ND6_SEND_FLAG_ALLNODES_DEST); 330 if (ip6_addr_istentative(netif_ip6_addr_state(inp, i))) { 331 /* We shouldn't use this address either. */ 332 netif_ip6_addr_set_state(inp, i, IP6_ADDR_INVALID); 333 } 334 } 335 } 336 } else { 337 ip6_addr_t target_address; 338 339 /* Sender is trying to resolve our address. */ 340 /* Verify that they included their own link-layer address. */ 341 if (lladdr_opt == NULL) { 342 /* Not a valid message. */ 343 pbuf_free(p); 344 ND6_STATS_INC(nd6.proterr); 345 ND6_STATS_INC(nd6.drop); 346 return; 347 } 348 349 i = nd6_find_neighbor_cache_entry(ip6_current_src_addr()); 350 if (i>= 0) { 351 /* We already have a record for the solicitor. */ 352 if (neighbor_cache[i].state == ND6_INCOMPLETE) { 353 neighbor_cache[i].netif = inp; 354 MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); 355 356 /* Delay probe in case we get confirmation of reachability from upper layer (TCP). */ 357 neighbor_cache[i].state = ND6_DELAY; 358 neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; 359 } 360 } else { 361 /* Add their IPv6 address and link-layer address to neighbor cache. 362 * We will need it at least to send a unicast NA message, but most 363 * likely we will also be communicating with this node soon. */ 364 i = nd6_new_neighbor_cache_entry(); 365 if (i < 0) { 366 /* We couldn't assign a cache entry for this neighbor. 367 * we won't be able to reply. drop it. */ 368 pbuf_free(p); 369 ND6_STATS_INC(nd6.memerr); 370 return; 371 } 372 neighbor_cache[i].netif = inp; 373 MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); 374 ip6_addr_set(&(neighbor_cache[i].next_hop_address), ip6_current_src_addr()); 375 376 /* Receiving a message does not prove reachability: only in one direction. 377 * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ 378 neighbor_cache[i].state = ND6_DELAY; 379 neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; 380 } 381 382 /* Create an aligned copy. */ 383 ip6_addr_set(&target_address, &(ns_hdr->target_address)); 384 385 /* Send back a NA for us. Allocate the reply pbuf. */ 386 nd6_send_na(inp, &target_address, ND6_FLAG_SOLICITED | ND6_FLAG_OVERRIDE); 387 } 388 389 break; /* ICMP6_TYPE_NS */ 390 } 391 case ICMP6_TYPE_RA: /* Router Advertisement. */ 392 { 393 struct ra_header *ra_hdr; 394 u8_t *buffer; /* Used to copy options. */ 395 u16_t offset; 396#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS 397 /* There can by multiple RDNSS options per RA */ 398 u8_t rdnss_server_idx = 0; 399#endif /* LWIP_ND6_RDNSS_MAX_DNS_SERVERS */ 400 401 /* Check that RA header fits in packet. */ 402 if (p->len < sizeof(struct ra_header)) { 403 /* @todo debug message */ 404 pbuf_free(p); 405 ND6_STATS_INC(nd6.lenerr); 406 ND6_STATS_INC(nd6.drop); 407 return; 408 } 409 410 ra_hdr = (struct ra_header *)p->payload; 411 412 /* If we are sending RS messages, stop. */ 413#if LWIP_IPV6_SEND_ROUTER_SOLICIT 414 /* ensure at least one solicitation is sent */ 415 if ((inp->rs_count < LWIP_ND6_MAX_MULTICAST_SOLICIT) || 416 (nd6_send_rs(inp) == ERR_OK)) { 417 inp->rs_count = 0; 418 } 419#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ 420 421 /* Get the matching default router entry. */ 422 i = nd6_get_router(ip6_current_src_addr(), inp); 423 if (i < 0) { 424 /* Create a new router entry. */ 425 i = nd6_new_router(ip6_current_src_addr(), inp); 426 } 427 428 if (i < 0) { 429 /* Could not create a new router entry. */ 430 pbuf_free(p); 431 ND6_STATS_INC(nd6.memerr); 432 return; 433 } 434 435 /* Re-set invalidation timer. */ 436 default_router_list[i].invalidation_timer = lwip_htons(ra_hdr->router_lifetime); 437 438 /* Re-set default timer values. */ 439#if LWIP_ND6_ALLOW_RA_UPDATES 440 if (ra_hdr->retrans_timer > 0) { 441 retrans_timer = lwip_htonl(ra_hdr->retrans_timer); 442 } 443 if (ra_hdr->reachable_time > 0) { 444 reachable_time = lwip_htonl(ra_hdr->reachable_time); 445 } 446#endif /* LWIP_ND6_ALLOW_RA_UPDATES */ 447 448 /* @todo set default hop limit... */ 449 /* ra_hdr->current_hop_limit;*/ 450 451 /* Update flags in local entry (incl. preference). */ 452 default_router_list[i].flags = ra_hdr->flags; 453 454 /* Offset to options. */ 455 offset = sizeof(struct ra_header); 456 457 /* Process each option. */ 458 while ((p->tot_len - offset) > 0) { 459 if (p->len == p->tot_len) { 460 /* no need to copy from contiguous pbuf */ 461 buffer = &((u8_t*)p->payload)[offset]; 462 } else { 463 buffer = nd6_ra_buffer; 464 if (pbuf_copy_partial(p, buffer, sizeof(struct prefix_option), offset) != sizeof(struct prefix_option)) { 465 pbuf_free(p); 466 ND6_STATS_INC(nd6.lenerr); 467 ND6_STATS_INC(nd6.drop); 468 return; 469 } 470 } 471 if (buffer[1] == 0) { 472 /* zero-length extension. drop packet */ 473 pbuf_free(p); 474 ND6_STATS_INC(nd6.lenerr); 475 ND6_STATS_INC(nd6.drop); 476 return; 477 } 478 switch (buffer[0]) { 479 case ND6_OPTION_TYPE_SOURCE_LLADDR: 480 { 481 struct lladdr_option *lladdr_opt; 482 lladdr_opt = (struct lladdr_option *)buffer; 483 if ((default_router_list[i].neighbor_entry != NULL) && 484 (default_router_list[i].neighbor_entry->state == ND6_INCOMPLETE)) { 485 SMEMCPY(default_router_list[i].neighbor_entry->lladdr, lladdr_opt->addr, inp->hwaddr_len); 486 default_router_list[i].neighbor_entry->state = ND6_REACHABLE; 487 default_router_list[i].neighbor_entry->counter.reachable_time = reachable_time; 488 } 489 break; 490 } 491 case ND6_OPTION_TYPE_MTU: 492 { 493 struct mtu_option *mtu_opt; 494 mtu_opt = (struct mtu_option *)buffer; 495 if (lwip_htonl(mtu_opt->mtu) >= 1280) { 496#if LWIP_ND6_ALLOW_RA_UPDATES 497 inp->mtu = (u16_t)lwip_htonl(mtu_opt->mtu); 498#endif /* LWIP_ND6_ALLOW_RA_UPDATES */ 499 } 500 break; 501 } 502 case ND6_OPTION_TYPE_PREFIX_INFO: 503 { 504 struct prefix_option *prefix_opt; 505 prefix_opt = (struct prefix_option *)buffer; 506 507 if ((prefix_opt->flags & ND6_PREFIX_FLAG_ON_LINK) && 508 (prefix_opt->prefix_length == 64) && 509 !ip6_addr_islinklocal(&(prefix_opt->prefix))) { 510 /* Add to on-link prefix list. */ 511 s8_t prefix; 512 ip6_addr_t prefix_addr; 513 514 /* Get a memory-aligned copy of the prefix. */ 515 ip6_addr_set(&prefix_addr, &(prefix_opt->prefix)); 516 517 /* find cache entry for this prefix. */ 518 prefix = nd6_get_onlink_prefix(&prefix_addr, inp); 519 if (prefix < 0) { 520 /* Create a new cache entry. */ 521 prefix = nd6_new_onlink_prefix(&prefix_addr, inp); 522 } 523 if (prefix >= 0) { 524 prefix_list[prefix].invalidation_timer = lwip_htonl(prefix_opt->valid_lifetime); 525 526#if LWIP_IPV6_AUTOCONFIG 527 if (prefix_opt->flags & ND6_PREFIX_FLAG_AUTONOMOUS) { 528 /* Mark prefix as autonomous, so that address autoconfiguration can take place. 529 * Only OR flag, so that we don't over-write other flags (such as ADDRESS_DUPLICATE)*/ 530 prefix_list[prefix].flags |= ND6_PREFIX_AUTOCONFIG_AUTONOMOUS; 531 } 532#endif /* LWIP_IPV6_AUTOCONFIG */ 533 } 534 } 535 536 break; 537 } 538 case ND6_OPTION_TYPE_ROUTE_INFO: 539 /* @todo implement preferred routes. 540 struct route_option * route_opt; 541 route_opt = (struct route_option *)buffer;*/ 542 543 break; 544#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS 545 case ND6_OPTION_TYPE_RDNSS: 546 { 547 u8_t num, n; 548 struct rdnss_option * rdnss_opt; 549 550 rdnss_opt = (struct rdnss_option *)buffer; 551 num = (rdnss_opt->length - 1) / 2; 552 for (n = 0; (rdnss_server_idx < DNS_MAX_SERVERS) && (n < num); n++) { 553 ip_addr_t rdnss_address; 554 555 /* Get a memory-aligned copy of the prefix. */ 556 ip_addr_copy_from_ip6(rdnss_address, rdnss_opt->rdnss_address[n]); 557 558 if (htonl(rdnss_opt->lifetime) > 0) { 559 /* TODO implement Lifetime > 0 */ 560 dns_setserver(rdnss_server_idx++, &rdnss_address); 561 } else { 562 /* TODO implement DNS removal in dns.c */ 563 u8_t s; 564 for (s = 0; s < DNS_MAX_SERVERS; s++) { 565 const ip_addr_t *addr = dns_getserver(s); 566 if(ip_addr_cmp(addr, &rdnss_address)) { 567 dns_setserver(s, NULL); 568 } 569 } 570 } 571 } 572 break; 573 } 574#endif /* LWIP_ND6_RDNSS_MAX_DNS_SERVERS */ 575 default: 576 /* Unrecognized option, abort. */ 577 ND6_STATS_INC(nd6.proterr); 578 break; 579 } 580 /* option length is checked earlier to be non-zero to make sure loop ends */ 581 offset += 8 * ((u16_t)buffer[1]); 582 } 583 584 break; /* ICMP6_TYPE_RA */ 585 } 586 case ICMP6_TYPE_RD: /* Redirect */ 587 { 588 struct redirect_header *redir_hdr; 589 struct lladdr_option *lladdr_opt; 590 ip6_addr_t tmp; 591 592 /* Check that Redir header fits in packet. */ 593 if (p->len < sizeof(struct redirect_header)) { 594 /* @todo debug message */ 595 pbuf_free(p); 596 ND6_STATS_INC(nd6.lenerr); 597 ND6_STATS_INC(nd6.drop); 598 return; 599 } 600 601 redir_hdr = (struct redirect_header *)p->payload; 602 603 if (p->len >= (sizeof(struct redirect_header) + 2)) { 604 lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct redirect_header)); 605 if (p->len < (sizeof(struct redirect_header) + (lladdr_opt->length << 3))) { 606 lladdr_opt = NULL; 607 } 608 } else { 609 lladdr_opt = NULL; 610 } 611 612 /* Copy original destination address to current source address, to have an aligned copy. */ 613 ip6_addr_set(&tmp, &(redir_hdr->destination_address)); 614 615 /* Find dest address in cache */ 616 i = nd6_find_destination_cache_entry(&tmp); 617 if (i < 0) { 618 /* Destination not in cache, drop packet. */ 619 pbuf_free(p); 620 return; 621 } 622 623 /* Set the new target address. */ 624 ip6_addr_set(&(destination_cache[i].next_hop_addr), &(redir_hdr->target_address)); 625 626 /* If Link-layer address of other router is given, try to add to neighbor cache. */ 627 if (lladdr_opt != NULL) { 628 if (lladdr_opt->type == ND6_OPTION_TYPE_TARGET_LLADDR) { 629 /* Copy target address to current source address, to have an aligned copy. */ 630 ip6_addr_set(&tmp, &(redir_hdr->target_address)); 631 632 i = nd6_find_neighbor_cache_entry(&tmp); 633 if (i < 0) { 634 i = nd6_new_neighbor_cache_entry(); 635 if (i >= 0) { 636 neighbor_cache[i].netif = inp; 637 MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); 638 ip6_addr_set(&(neighbor_cache[i].next_hop_address), &tmp); 639 640 /* Receiving a message does not prove reachability: only in one direction. 641 * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ 642 neighbor_cache[i].state = ND6_DELAY; 643 neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; 644 } 645 } 646 if (i >= 0) { 647 if (neighbor_cache[i].state == ND6_INCOMPLETE) { 648 MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); 649 /* Receiving a message does not prove reachability: only in one direction. 650 * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ 651 neighbor_cache[i].state = ND6_DELAY; 652 neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; 653 } 654 } 655 } 656 } 657 break; /* ICMP6_TYPE_RD */ 658 } 659 case ICMP6_TYPE_PTB: /* Packet too big */ 660 { 661 struct icmp6_hdr *icmp6hdr; /* Packet too big message */ 662 struct ip6_hdr *ip6hdr; /* IPv6 header of the packet which caused the error */ 663 u32_t pmtu; 664 ip6_addr_t tmp; 665 666 /* Check that ICMPv6 header + IPv6 header fit in payload */ 667 if (p->len < (sizeof(struct icmp6_hdr) + IP6_HLEN)) { 668 /* drop short packets */ 669 pbuf_free(p); 670 ND6_STATS_INC(nd6.lenerr); 671 ND6_STATS_INC(nd6.drop); 672 return; 673 } 674 675 icmp6hdr = (struct icmp6_hdr *)p->payload; 676 ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmp6_hdr)); 677 678 /* Copy original destination address to current source address, to have an aligned copy. */ 679 ip6_addr_set(&tmp, &(ip6hdr->dest)); 680 681 /* Look for entry in destination cache. */ 682 i = nd6_find_destination_cache_entry(&tmp); 683 if (i < 0) { 684 /* Destination not in cache, drop packet. */ 685 pbuf_free(p); 686 return; 687 } 688 689 /* Change the Path MTU. */ 690 pmtu = lwip_htonl(icmp6hdr->data); 691 destination_cache[i].pmtu = (u16_t)LWIP_MIN(pmtu, 0xFFFF); 692 693 break; /* ICMP6_TYPE_PTB */ 694 } 695 696 default: 697 ND6_STATS_INC(nd6.proterr); 698 ND6_STATS_INC(nd6.drop); 699 break; /* default */ 700 } 701 702 pbuf_free(p); 703} 704 705 706/** 707 * Periodic timer for Neighbor discovery functions: 708 * 709 * - Update neighbor reachability states 710 * - Update destination cache entries age 711 * - Update invalidation timers of default routers and on-link prefixes 712 * - Perform duplicate address detection (DAD) for our addresses 713 * - Send router solicitations 714 */ 715void 716nd6_tmr(void) 717{ 718 s8_t i; 719 struct netif *netif; 720 721 /* Process neighbor entries. */ 722 for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { 723 switch (neighbor_cache[i].state) { 724 case ND6_INCOMPLETE: 725 if ((neighbor_cache[i].counter.probes_sent >= LWIP_ND6_MAX_MULTICAST_SOLICIT) && 726 (!neighbor_cache[i].isrouter)) { 727 /* Retries exceeded. */ 728 nd6_free_neighbor_cache_entry(i); 729 } else { 730 /* Send a NS for this entry. */ 731 neighbor_cache[i].counter.probes_sent++; 732 nd6_send_neighbor_cache_probe(&neighbor_cache[i], ND6_SEND_FLAG_MULTICAST_DEST); 733 } 734 break; 735 case ND6_REACHABLE: 736 /* Send queued packets, if any are left. Should have been sent already. */ 737 if (neighbor_cache[i].q != NULL) { 738 nd6_send_q(i); 739 } 740 if (neighbor_cache[i].counter.reachable_time <= ND6_TMR_INTERVAL) { 741 /* Change to stale state. */ 742 neighbor_cache[i].state = ND6_STALE; 743 neighbor_cache[i].counter.stale_time = 0; 744 } else { 745 neighbor_cache[i].counter.reachable_time -= ND6_TMR_INTERVAL; 746 } 747 break; 748 case ND6_STALE: 749 neighbor_cache[i].counter.stale_time++; 750 break; 751 case ND6_DELAY: 752 if (neighbor_cache[i].counter.delay_time <= 1) { 753 /* Change to PROBE state. */ 754 neighbor_cache[i].state = ND6_PROBE; 755 neighbor_cache[i].counter.probes_sent = 0; 756 } else { 757 neighbor_cache[i].counter.delay_time--; 758 } 759 break; 760 case ND6_PROBE: 761 if ((neighbor_cache[i].counter.probes_sent >= LWIP_ND6_MAX_MULTICAST_SOLICIT) && 762 (!neighbor_cache[i].isrouter)) { 763 /* Retries exceeded. */ 764 nd6_free_neighbor_cache_entry(i); 765 } else { 766 /* Send a NS for this entry. */ 767 neighbor_cache[i].counter.probes_sent++; 768 nd6_send_neighbor_cache_probe(&neighbor_cache[i], 0); 769 } 770 break; 771 case ND6_NO_ENTRY: 772 default: 773 /* Do nothing. */ 774 break; 775 } 776 } 777 778 /* Process destination entries. */ 779 for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { 780 destination_cache[i].age++; 781 } 782 783 /* Process router entries. */ 784 for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { 785 if (default_router_list[i].neighbor_entry != NULL) { 786 /* Active entry. */ 787 if (default_router_list[i].invalidation_timer > 0) { 788 default_router_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000; 789 } 790 if (default_router_list[i].invalidation_timer < ND6_TMR_INTERVAL / 1000) { 791 /* Less than 1 second remaining. Clear this entry. */ 792 default_router_list[i].neighbor_entry->isrouter = 0; 793 default_router_list[i].neighbor_entry = NULL; 794 default_router_list[i].invalidation_timer = 0; 795 default_router_list[i].flags = 0; 796 } 797 } 798 } 799 800 /* Process prefix entries. */ 801 for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { 802 if (prefix_list[i].netif != NULL) { 803 if (prefix_list[i].invalidation_timer < ND6_TMR_INTERVAL / 1000) { 804 /* Entry timed out, remove it */ 805 prefix_list[i].invalidation_timer = 0; 806 807#if LWIP_IPV6_AUTOCONFIG 808 /* If any addresses were configured with this prefix, remove them */ 809 if (prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED) { 810 s8_t j; 811 812 for (j = 1; j < LWIP_IPV6_NUM_ADDRESSES; j++) { 813 if ((netif_ip6_addr_state(prefix_list[i].netif, j) != IP6_ADDR_INVALID) && 814 ip6_addr_netcmp(&prefix_list[i].prefix, netif_ip6_addr(prefix_list[i].netif, j))) { 815 netif_ip6_addr_set_state(prefix_list[i].netif, j, IP6_ADDR_INVALID); 816 prefix_list[i].flags = 0; 817 818 /* Exit loop. */ 819 break; 820 } 821 } 822 } 823#endif /* LWIP_IPV6_AUTOCONFIG */ 824 825 prefix_list[i].netif = NULL; 826 prefix_list[i].flags = 0; 827 } else { 828 prefix_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000; 829 830#if LWIP_IPV6_AUTOCONFIG 831 /* Initiate address autoconfiguration for this prefix, if conditions are met. */ 832 if (prefix_list[i].netif->ip6_autoconfig_enabled && 833 (prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_AUTONOMOUS) && 834 !(prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED)) { 835 s8_t j; 836 /* Try to get an address on this netif that is invalid. 837 * Skip 0 index (link-local address) */ 838 for (j = 1; j < LWIP_IPV6_NUM_ADDRESSES; j++) { 839 if (netif_ip6_addr_state(prefix_list[i].netif, j) == IP6_ADDR_INVALID) { 840 /* Generate an address using this prefix and interface ID from link-local address. */ 841 netif_ip6_addr_set_parts(prefix_list[i].netif, j, 842 prefix_list[i].prefix.addr[0], prefix_list[i].prefix.addr[1], 843 netif_ip6_addr(prefix_list[i].netif, 0)->addr[2], netif_ip6_addr(prefix_list[i].netif, 0)->addr[3]); 844 845 /* Mark it as tentative (DAD will be performed if configured). */ 846 netif_ip6_addr_set_state(prefix_list[i].netif, j, IP6_ADDR_TENTATIVE); 847 848 /* Mark this prefix with ADDRESS_GENERATED, so that we don't try again. */ 849 prefix_list[i].flags |= ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED; 850 851 /* Exit loop. */ 852 break; 853 } 854 } 855 } 856#endif /* LWIP_IPV6_AUTOCONFIG */ 857 } 858 } 859 } 860 861 862 /* Process our own addresses, if DAD configured. */ 863 for (netif = netif_list; netif != NULL; netif = netif->next) { 864 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { 865 u8_t addr_state = netif_ip6_addr_state(netif, i); 866 if (ip6_addr_istentative(addr_state)) { 867 if ((addr_state & IP6_ADDR_TENTATIVE_COUNT_MASK) >= LWIP_IPV6_DUP_DETECT_ATTEMPTS) { 868 /* No NA received in response. Mark address as valid. */ 869 netif_ip6_addr_set_state(netif, i, IP6_ADDR_PREFERRED); 870 /* @todo implement preferred and valid lifetimes. */ 871 } else if (netif->flags & NETIF_FLAG_UP) { 872 /* Send a NS for this address. */ 873 nd6_send_ns(netif, netif_ip6_addr(netif, i), ND6_SEND_FLAG_MULTICAST_DEST); 874 /* tentative: set next state by increasing by one */ 875 netif_ip6_addr_set_state(netif, i, addr_state + 1); 876 /* @todo send max 1 NS per tmr call? enable return*/ 877 /*return;*/ 878 } 879 } 880 } 881 } 882 883#if LWIP_IPV6_SEND_ROUTER_SOLICIT 884 /* Send router solicitation messages, if necessary. */ 885 for (netif = netif_list; netif != NULL; netif = netif->next) { 886 if ((netif->rs_count > 0) && (netif->flags & NETIF_FLAG_UP) && 887 (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, 0)))) { 888 if (nd6_send_rs(netif) == ERR_OK) { 889 netif->rs_count--; 890 } 891 } 892 } 893#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ 894 895} 896 897/** Send a neighbor solicitation message for a specific neighbor cache entry 898 * 899 * @param entry the neightbor cache entry for wich to send the message 900 * @param flags one of ND6_SEND_FLAG_* 901 */ 902static void 903nd6_send_neighbor_cache_probe(struct nd6_neighbor_cache_entry *entry, u8_t flags) 904{ 905 nd6_send_ns(entry->netif, &entry->next_hop_address, flags); 906} 907 908/** 909 * Send a neighbor solicitation message 910 * 911 * @param netif the netif on which to send the message 912 * @param target_addr the IPv6 target address for the ND message 913 * @param flags one of ND6_SEND_FLAG_* 914 */ 915static void 916nd6_send_ns(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags) 917{ 918 struct ns_header *ns_hdr; 919 struct pbuf *p; 920 const ip6_addr_t *src_addr; 921 u16_t lladdr_opt_len; 922 923 if (ip6_addr_isvalid(netif_ip6_addr_state(netif,0))) { 924 /* Use link-local address as source address. */ 925 src_addr = netif_ip6_addr(netif, 0); 926 /* calculate option length (in 8-byte-blocks) */ 927 lladdr_opt_len = ((netif->hwaddr_len + 2) + 7) >> 3; 928 } else { 929 src_addr = IP6_ADDR_ANY6; 930 /* Option "MUST NOT be included when the source IP address is the unspecified address." */ 931 lladdr_opt_len = 0; 932 } 933 934 /* Allocate a packet. */ 935 p = pbuf_alloc(PBUF_IP, sizeof(struct ns_header) + (lladdr_opt_len << 3), PBUF_RAM); 936 if (p == NULL) { 937 ND6_STATS_INC(nd6.memerr); 938 return; 939 } 940 941 /* Set fields. */ 942 ns_hdr = (struct ns_header *)p->payload; 943 944 ns_hdr->type = ICMP6_TYPE_NS; 945 ns_hdr->code = 0; 946 ns_hdr->chksum = 0; 947 ns_hdr->reserved = 0; 948 ip6_addr_set(&(ns_hdr->target_address), target_addr); 949 950 if (lladdr_opt_len != 0) { 951 struct lladdr_option *lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct ns_header)); 952 lladdr_opt->type = ND6_OPTION_TYPE_SOURCE_LLADDR; 953 lladdr_opt->length = (u8_t)lladdr_opt_len; 954 SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); 955 } 956 957 /* Generate the solicited node address for the target address. */ 958 if (flags & ND6_SEND_FLAG_MULTICAST_DEST) { 959 ip6_addr_set_solicitednode(&multicast_address, target_addr->addr[3]); 960 target_addr = &multicast_address; 961 } 962 963#if CHECKSUM_GEN_ICMP6 964 IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { 965 ns_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, 966 target_addr); 967 } 968#endif /* CHECKSUM_GEN_ICMP6 */ 969 970 /* Send the packet out. */ 971 ND6_STATS_INC(nd6.xmit); 972 ip6_output_if(p, (src_addr == IP6_ADDR_ANY6) ? NULL : src_addr, target_addr, 973 LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); 974 pbuf_free(p); 975} 976 977/** 978 * Send a neighbor advertisement message 979 * 980 * @param netif the netif on which to send the message 981 * @param target_addr the IPv6 target address for the ND message 982 * @param flags one of ND6_SEND_FLAG_* 983 */ 984static void 985nd6_send_na(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags) 986{ 987 struct na_header *na_hdr; 988 struct lladdr_option *lladdr_opt; 989 struct pbuf *p; 990 const ip6_addr_t *src_addr; 991 const ip6_addr_t *dest_addr; 992 u16_t lladdr_opt_len; 993 994 /* Use link-local address as source address. */ 995 /* src_addr = netif_ip6_addr(netif, 0); */ 996 /* Use target address as source address. */ 997 src_addr = target_addr; 998 999 /* Allocate a packet. */ 1000 lladdr_opt_len = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0); 1001 p = pbuf_alloc(PBUF_IP, sizeof(struct na_header) + (lladdr_opt_len << 3), PBUF_RAM); 1002 if (p == NULL) { 1003 ND6_STATS_INC(nd6.memerr); 1004 return; 1005 } 1006 1007 /* Set fields. */ 1008 na_hdr = (struct na_header *)p->payload; 1009 lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); 1010 1011 na_hdr->type = ICMP6_TYPE_NA; 1012 na_hdr->code = 0; 1013 na_hdr->chksum = 0; 1014 na_hdr->flags = flags & 0xf0; 1015 na_hdr->reserved[0] = 0; 1016 na_hdr->reserved[1] = 0; 1017 na_hdr->reserved[2] = 0; 1018 ip6_addr_set(&(na_hdr->target_address), target_addr); 1019 1020 lladdr_opt->type = ND6_OPTION_TYPE_TARGET_LLADDR; 1021 lladdr_opt->length = (u8_t)lladdr_opt_len; 1022 SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); 1023 1024 /* Generate the solicited node address for the target address. */ 1025 if (flags & ND6_SEND_FLAG_MULTICAST_DEST) { 1026 ip6_addr_set_solicitednode(&multicast_address, target_addr->addr[3]); 1027 dest_addr = &multicast_address; 1028 } else if (flags & ND6_SEND_FLAG_ALLNODES_DEST) { 1029 ip6_addr_set_allnodes_linklocal(&multicast_address); 1030 dest_addr = &multicast_address; 1031 } else { 1032 dest_addr = ip6_current_src_addr(); 1033 } 1034 1035#if CHECKSUM_GEN_ICMP6 1036 IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { 1037 na_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, 1038 dest_addr); 1039 } 1040#endif /* CHECKSUM_GEN_ICMP6 */ 1041 1042 /* Send the packet out. */ 1043 ND6_STATS_INC(nd6.xmit); 1044 ip6_output_if(p, src_addr, dest_addr, 1045 LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); 1046 pbuf_free(p); 1047} 1048 1049#if LWIP_IPV6_SEND_ROUTER_SOLICIT 1050/** 1051 * Send a router solicitation message 1052 * 1053 * @param netif the netif on which to send the message 1054 */ 1055static err_t 1056nd6_send_rs(struct netif *netif) 1057{ 1058 struct rs_header *rs_hdr; 1059 struct lladdr_option *lladdr_opt; 1060 struct pbuf *p; 1061 const ip6_addr_t *src_addr; 1062 err_t err; 1063 u16_t lladdr_opt_len = 0; 1064 1065 /* Link-local source address, or unspecified address? */ 1066 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, 0))) { 1067 src_addr = netif_ip6_addr(netif, 0); 1068 } else { 1069 src_addr = IP6_ADDR_ANY6; 1070 } 1071 1072 /* Generate the all routers target address. */ 1073 ip6_addr_set_allrouters_linklocal(&multicast_address); 1074 1075 /* Allocate a packet. */ 1076 if (src_addr != IP6_ADDR_ANY6) { 1077 lladdr_opt_len = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0); 1078 } 1079 p = pbuf_alloc(PBUF_IP, sizeof(struct rs_header) + (lladdr_opt_len << 3), PBUF_RAM); 1080 if (p == NULL) { 1081 ND6_STATS_INC(nd6.memerr); 1082 return ERR_BUF; 1083 } 1084 1085 /* Set fields. */ 1086 rs_hdr = (struct rs_header *)p->payload; 1087 1088 rs_hdr->type = ICMP6_TYPE_RS; 1089 rs_hdr->code = 0; 1090 rs_hdr->chksum = 0; 1091 rs_hdr->reserved = 0; 1092 1093 if (src_addr != IP6_ADDR_ANY6) { 1094 /* Include our hw address. */ 1095 lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct rs_header)); 1096 lladdr_opt->type = ND6_OPTION_TYPE_SOURCE_LLADDR; 1097 lladdr_opt->length = (u8_t)lladdr_opt_len; 1098 SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); 1099 } 1100 1101#if CHECKSUM_GEN_ICMP6 1102 IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { 1103 rs_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, 1104 &multicast_address); 1105 } 1106#endif /* CHECKSUM_GEN_ICMP6 */ 1107 1108 /* Send the packet out. */ 1109 ND6_STATS_INC(nd6.xmit); 1110 1111 err = ip6_output_if(p, (src_addr == IP6_ADDR_ANY6) ? NULL : src_addr, &multicast_address, 1112 LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); 1113 pbuf_free(p); 1114 1115 return err; 1116} 1117#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ 1118 1119/** 1120 * Search for a neighbor cache entry 1121 * 1122 * @param ip6addr the IPv6 address of the neighbor 1123 * @return The neighbor cache entry index that matched, -1 if no 1124 * entry is found 1125 */ 1126static s8_t 1127nd6_find_neighbor_cache_entry(const ip6_addr_t *ip6addr) 1128{ 1129 s8_t i; 1130 for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { 1131 if (ip6_addr_cmp(ip6addr, &(neighbor_cache[i].next_hop_address))) { 1132 return i; 1133 } 1134 } 1135 return -1; 1136} 1137 1138/** 1139 * Create a new neighbor cache entry. 1140 * 1141 * If no unused entry is found, will try to recycle an old entry 1142 * according to ad-hoc "age" heuristic. 1143 * 1144 * @return The neighbor cache entry index that was created, -1 if no 1145 * entry could be created 1146 */ 1147static s8_t 1148nd6_new_neighbor_cache_entry(void) 1149{ 1150 s8_t i; 1151 s8_t j; 1152 u32_t time; 1153 1154 1155 /* First, try to find an empty entry. */ 1156 for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { 1157 if (neighbor_cache[i].state == ND6_NO_ENTRY) { 1158 return i; 1159 } 1160 } 1161 1162 /* We need to recycle an entry. in general, do not recycle if it is a router. */ 1163 1164 /* Next, try to find a Stale entry. */ 1165 for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { 1166 if ((neighbor_cache[i].state == ND6_STALE) && 1167 (!neighbor_cache[i].isrouter)) { 1168 nd6_free_neighbor_cache_entry(i); 1169 return i; 1170 } 1171 } 1172 1173 /* Next, try to find a Probe entry. */ 1174 for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { 1175 if ((neighbor_cache[i].state == ND6_PROBE) && 1176 (!neighbor_cache[i].isrouter)) { 1177 nd6_free_neighbor_cache_entry(i); 1178 return i; 1179 } 1180 } 1181 1182 /* Next, try to find a Delayed entry. */ 1183 for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { 1184 if ((neighbor_cache[i].state == ND6_DELAY) && 1185 (!neighbor_cache[i].isrouter)) { 1186 nd6_free_neighbor_cache_entry(i); 1187 return i; 1188 } 1189 } 1190 1191 /* Next, try to find the oldest reachable entry. */ 1192 time = 0xfffffffful; 1193 j = -1; 1194 for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { 1195 if ((neighbor_cache[i].state == ND6_REACHABLE) && 1196 (!neighbor_cache[i].isrouter)) { 1197 if (neighbor_cache[i].counter.reachable_time < time) { 1198 j = i; 1199 time = neighbor_cache[i].counter.reachable_time; 1200 } 1201 } 1202 } 1203 if (j >= 0) { 1204 nd6_free_neighbor_cache_entry(j); 1205 return j; 1206 } 1207 1208 /* Next, find oldest incomplete entry without queued packets. */ 1209 time = 0; 1210 j = -1; 1211 for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { 1212 if ( 1213 (neighbor_cache[i].q == NULL) && 1214 (neighbor_cache[i].state == ND6_INCOMPLETE) && 1215 (!neighbor_cache[i].isrouter)) { 1216 if (neighbor_cache[i].counter.probes_sent >= time) { 1217 j = i; 1218 time = neighbor_cache[i].counter.probes_sent; 1219 } 1220 } 1221 } 1222 if (j >= 0) { 1223 nd6_free_neighbor_cache_entry(j); 1224 return j; 1225 } 1226 1227 /* Next, find oldest incomplete entry with queued packets. */ 1228 time = 0; 1229 j = -1; 1230 for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { 1231 if ((neighbor_cache[i].state == ND6_INCOMPLETE) && 1232 (!neighbor_cache[i].isrouter)) { 1233 if (neighbor_cache[i].counter.probes_sent >= time) { 1234 j = i; 1235 time = neighbor_cache[i].counter.probes_sent; 1236 } 1237 } 1238 } 1239 if (j >= 0) { 1240 nd6_free_neighbor_cache_entry(j); 1241 return j; 1242 } 1243 1244 /* No more entries to try. */ 1245 return -1; 1246} 1247 1248/** 1249 * Will free any resources associated with a neighbor cache 1250 * entry, and will mark it as unused. 1251 * 1252 * @param i the neighbor cache entry index to free 1253 */ 1254static void 1255nd6_free_neighbor_cache_entry(s8_t i) 1256{ 1257 if ((i < 0) || (i >= LWIP_ND6_NUM_NEIGHBORS)) { 1258 return; 1259 } 1260 if (neighbor_cache[i].isrouter) { 1261 /* isrouter needs to be cleared before deleting a neighbor cache entry */ 1262 return; 1263 } 1264 1265 /* Free any queued packets. */ 1266 if (neighbor_cache[i].q != NULL) { 1267 nd6_free_q(neighbor_cache[i].q); 1268 neighbor_cache[i].q = NULL; 1269 } 1270 1271 neighbor_cache[i].state = ND6_NO_ENTRY; 1272 neighbor_cache[i].isrouter = 0; 1273 neighbor_cache[i].netif = NULL; 1274 neighbor_cache[i].counter.reachable_time = 0; 1275 ip6_addr_set_zero(&(neighbor_cache[i].next_hop_address)); 1276} 1277 1278/** 1279 * Search for a destination cache entry 1280 * 1281 * @param ip6addr the IPv6 address of the destination 1282 * @return The destination cache entry index that matched, -1 if no 1283 * entry is found 1284 */ 1285static s8_t 1286nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr) 1287{ 1288 s8_t i; 1289 for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { 1290 if (ip6_addr_cmp(ip6addr, &(destination_cache[i].destination_addr))) { 1291 return i; 1292 } 1293 } 1294 return -1; 1295} 1296 1297/** 1298 * Create a new destination cache entry. If no unused entry is found, 1299 * will recycle oldest entry. 1300 * 1301 * @return The destination cache entry index that was created, -1 if no 1302 * entry was created 1303 */ 1304static s8_t 1305nd6_new_destination_cache_entry(void) 1306{ 1307 s8_t i, j; 1308 u32_t age; 1309 1310 /* Find an empty entry. */ 1311 for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { 1312 if (ip6_addr_isany(&(destination_cache[i].destination_addr))) { 1313 return i; 1314 } 1315 } 1316 1317 /* Find oldest entry. */ 1318 age = 0; 1319 j = LWIP_ND6_NUM_DESTINATIONS - 1; 1320 for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { 1321 if (destination_cache[i].age > age) { 1322 j = i; 1323 } 1324 } 1325 1326 return j; 1327} 1328 1329/** 1330 * Clear the destination cache. 1331 * 1332 * This operation may be necessary for consistency in the light of changing 1333 * local addresses and/or use of the gateway hook. 1334 */ 1335void 1336nd6_clear_destination_cache(void) 1337{ 1338 int i; 1339 1340 for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { 1341 ip6_addr_set_any(&destination_cache[i].destination_addr); 1342 } 1343} 1344 1345/** 1346 * Determine whether an address matches an on-link prefix. 1347 * 1348 * @param ip6addr the IPv6 address to match 1349 * @return 1 if the address is on-link, 0 otherwise 1350 */ 1351static s8_t 1352nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif) 1353{ 1354 s8_t i; 1355 for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { 1356 if ((prefix_list[i].netif == netif) && 1357 (prefix_list[i].invalidation_timer > 0) && 1358 ip6_addr_netcmp(ip6addr, &(prefix_list[i].prefix))) { 1359 return 1; 1360 } 1361 } 1362 /* Check to see if address prefix matches a (manually?) configured address. */ 1363 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 1364 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && 1365 ip6_addr_netcmp(ip6addr, netif_ip6_addr(netif, i))) { 1366 return 1; 1367 } 1368 } 1369 return 0; 1370} 1371 1372/** 1373 * Select a default router for a destination. 1374 * 1375 * @param ip6addr the destination address 1376 * @param netif the netif for the outgoing packet, if known 1377 * @return the default router entry index, or -1 if no suitable 1378 * router is found 1379 */ 1380static s8_t 1381nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif) 1382{ 1383 s8_t i; 1384 /* last_router is used for round-robin router selection (as recommended 1385 * in RFC). This is more robust in case one router is not reachable, 1386 * we are not stuck trying to resolve it. */ 1387 static s8_t last_router; 1388 (void)ip6addr; /* @todo match preferred routes!! (must implement ND6_OPTION_TYPE_ROUTE_INFO) */ 1389 1390 /* @todo: implement default router preference */ 1391 1392 /* Look for reachable routers. */ 1393 for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { 1394 if (++last_router >= LWIP_ND6_NUM_ROUTERS) { 1395 last_router = 0; 1396 } 1397 if ((default_router_list[i].neighbor_entry != NULL) && 1398 (netif != NULL ? netif == default_router_list[i].neighbor_entry->netif : 1) && 1399 (default_router_list[i].invalidation_timer > 0) && 1400 (default_router_list[i].neighbor_entry->state == ND6_REACHABLE)) { 1401 return i; 1402 } 1403 } 1404 1405 /* Look for router in other reachability states, but still valid according to timer. */ 1406 for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { 1407 if (++last_router >= LWIP_ND6_NUM_ROUTERS) { 1408 last_router = 0; 1409 } 1410 if ((default_router_list[i].neighbor_entry != NULL) && 1411 (netif != NULL ? netif == default_router_list[i].neighbor_entry->netif : 1) && 1412 (default_router_list[i].invalidation_timer > 0)) { 1413 return i; 1414 } 1415 } 1416 1417 /* Look for any router for which we have any information at all. */ 1418 for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { 1419 if (++last_router >= LWIP_ND6_NUM_ROUTERS) { 1420 last_router = 0; 1421 } 1422 if (default_router_list[i].neighbor_entry != NULL && 1423 (netif != NULL ? netif == default_router_list[i].neighbor_entry->netif : 1)) { 1424 return i; 1425 } 1426 } 1427 1428 /* no suitable router found. */ 1429 return -1; 1430} 1431 1432/** 1433 * Find a router-announced route to the given destination. 1434 * 1435 * The caller is responsible for checking whether the returned netif, if any, 1436 * is in a suitable state (up, link up) to be used for packet transmission. 1437 * 1438 * @param ip6addr the destination IPv6 address 1439 * @return the netif to use for the destination, or NULL if none found 1440 */ 1441struct netif * 1442nd6_find_route(const ip6_addr_t *ip6addr) 1443{ 1444 s8_t i; 1445 1446 i = nd6_select_router(ip6addr, NULL); 1447 if (i >= 0) { 1448 if (default_router_list[i].neighbor_entry != NULL) { 1449 return default_router_list[i].neighbor_entry->netif; /* may be NULL */ 1450 } 1451 } 1452 1453 return NULL; 1454} 1455 1456/** 1457 * Find an entry for a default router. 1458 * 1459 * @param router_addr the IPv6 address of the router 1460 * @param netif the netif on which the router is found, if known 1461 * @return the index of the router entry, or -1 if not found 1462 */ 1463static s8_t 1464nd6_get_router(const ip6_addr_t *router_addr, struct netif *netif) 1465{ 1466 s8_t i; 1467 1468 /* Look for router. */ 1469 for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { 1470 if ((default_router_list[i].neighbor_entry != NULL) && 1471 ((netif != NULL) ? netif == default_router_list[i].neighbor_entry->netif : 1) && 1472 ip6_addr_cmp(router_addr, &(default_router_list[i].neighbor_entry->next_hop_address))) { 1473 return i; 1474 } 1475 } 1476 1477 /* router not found. */ 1478 return -1; 1479} 1480 1481/** 1482 * Create a new entry for a default router. 1483 * 1484 * @param router_addr the IPv6 address of the router 1485 * @param netif the netif on which the router is connected, if known 1486 * @return the index on the router table, or -1 if could not be created 1487 */ 1488static s8_t 1489nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif) 1490{ 1491 s8_t router_index; 1492 s8_t free_router_index; 1493 s8_t neighbor_index; 1494 1495 /* Do we have a neighbor entry for this router? */ 1496 neighbor_index = nd6_find_neighbor_cache_entry(router_addr); 1497 if (neighbor_index < 0) { 1498 /* Create a neighbor entry for this router. */ 1499 neighbor_index = nd6_new_neighbor_cache_entry(); 1500 if (neighbor_index < 0) { 1501 /* Could not create neighbor entry for this router. */ 1502 return -1; 1503 } 1504 ip6_addr_set(&(neighbor_cache[neighbor_index].next_hop_address), router_addr); 1505 neighbor_cache[neighbor_index].netif = netif; 1506 neighbor_cache[neighbor_index].q = NULL; 1507 neighbor_cache[neighbor_index].state = ND6_INCOMPLETE; 1508 neighbor_cache[neighbor_index].counter.probes_sent = 1; 1509 nd6_send_neighbor_cache_probe(&neighbor_cache[neighbor_index], ND6_SEND_FLAG_MULTICAST_DEST); 1510 } 1511 1512 /* Mark neighbor as router. */ 1513 neighbor_cache[neighbor_index].isrouter = 1; 1514 1515 /* Look for empty entry. */ 1516 free_router_index = LWIP_ND6_NUM_ROUTERS; 1517 for (router_index = LWIP_ND6_NUM_ROUTERS - 1; router_index >= 0; router_index--) { 1518 /* check if router already exists (this is a special case for 2 netifs on the same subnet 1519 - e.g. wifi and cable) */ 1520 if(default_router_list[router_index].neighbor_entry == &(neighbor_cache[neighbor_index])){ 1521 return router_index; 1522 } 1523 if (default_router_list[router_index].neighbor_entry == NULL) { 1524 /* remember lowest free index to create a new entry */ 1525 free_router_index = router_index; 1526 } 1527 } 1528 if (free_router_index < LWIP_ND6_NUM_ROUTERS) { 1529 default_router_list[free_router_index].neighbor_entry = &(neighbor_cache[neighbor_index]); 1530 return free_router_index; 1531 } 1532 1533 /* Could not create a router entry. */ 1534 1535 /* Mark neighbor entry as not-router. Entry might be useful as neighbor still. */ 1536 neighbor_cache[neighbor_index].isrouter = 0; 1537 1538 /* router not found. */ 1539 return -1; 1540} 1541 1542/** 1543 * Find the cached entry for an on-link prefix. 1544 * 1545 * @param prefix the IPv6 prefix that is on-link 1546 * @param netif the netif on which the prefix is on-link 1547 * @return the index on the prefix table, or -1 if not found 1548 */ 1549static s8_t 1550nd6_get_onlink_prefix(ip6_addr_t *prefix, struct netif *netif) 1551{ 1552 s8_t i; 1553 1554 /* Look for prefix in list. */ 1555 for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) { 1556 if ((ip6_addr_netcmp(&(prefix_list[i].prefix), prefix)) && 1557 (prefix_list[i].netif == netif)) { 1558 return i; 1559 } 1560 } 1561 1562 /* Entry not available. */ 1563 return -1; 1564} 1565 1566/** 1567 * Creates a new entry for an on-link prefix. 1568 * 1569 * @param prefix the IPv6 prefix that is on-link 1570 * @param netif the netif on which the prefix is on-link 1571 * @return the index on the prefix table, or -1 if not created 1572 */ 1573static s8_t 1574nd6_new_onlink_prefix(ip6_addr_t *prefix, struct netif *netif) 1575{ 1576 s8_t i; 1577 1578 /* Create new entry. */ 1579 for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) { 1580 if ((prefix_list[i].netif == NULL) || 1581 (prefix_list[i].invalidation_timer == 0)) { 1582 /* Found empty prefix entry. */ 1583 prefix_list[i].netif = netif; 1584 ip6_addr_set(&(prefix_list[i].prefix), prefix); 1585#if LWIP_IPV6_AUTOCONFIG 1586 prefix_list[i].flags = 0; 1587#endif /* LWIP_IPV6_AUTOCONFIG */ 1588 return i; 1589 } 1590 } 1591 1592 /* Entry not available. */ 1593 return -1; 1594} 1595 1596/** 1597 * Determine the next hop for a destination. Will determine if the 1598 * destination is on-link, else a suitable on-link router is selected. 1599 * 1600 * The last entry index is cached for fast entry search. 1601 * 1602 * @param ip6addr the destination address 1603 * @param netif the netif on which the packet will be sent 1604 * @return the neighbor cache entry for the next hop, ERR_RTE if no 1605 * suitable next hop was found, ERR_MEM if no cache entry 1606 * could be created 1607 */ 1608static s8_t 1609nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif) 1610{ 1611#ifdef LWIP_HOOK_ND6_GET_GW 1612 const ip6_addr_t *next_hop_addr; 1613#endif /* LWIP_HOOK_ND6_GET_GW */ 1614 s8_t i; 1615 1616#if LWIP_NETIF_HWADDRHINT 1617 if (netif->addr_hint != NULL) { 1618 /* per-pcb cached entry was given */ 1619 u8_t addr_hint = *(netif->addr_hint); 1620 if (addr_hint < LWIP_ND6_NUM_DESTINATIONS) { 1621 nd6_cached_destination_index = addr_hint; 1622 } 1623 } 1624#endif /* LWIP_NETIF_HWADDRHINT */ 1625 1626 /* Look for ip6addr in destination cache. */ 1627 if (ip6_addr_cmp(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) { 1628 /* the cached entry index is the right one! */ 1629 /* do nothing. */ 1630 ND6_STATS_INC(nd6.cachehit); 1631 } else { 1632 /* Search destination cache. */ 1633 i = nd6_find_destination_cache_entry(ip6addr); 1634 if (i >= 0) { 1635 /* found destination entry. make it our new cached index. */ 1636 nd6_cached_destination_index = i; 1637 } else { 1638 /* Not found. Create a new destination entry. */ 1639 i = nd6_new_destination_cache_entry(); 1640 if (i >= 0) { 1641 /* got new destination entry. make it our new cached index. */ 1642 nd6_cached_destination_index = i; 1643 } else { 1644 /* Could not create a destination cache entry. */ 1645 return ERR_MEM; 1646 } 1647 1648 /* Copy dest address to destination cache. */ 1649 ip6_addr_set(&(destination_cache[nd6_cached_destination_index].destination_addr), ip6addr); 1650 1651 /* Now find the next hop. is it a neighbor? */ 1652 if (ip6_addr_islinklocal(ip6addr) || 1653 nd6_is_prefix_in_netif(ip6addr, netif)) { 1654 /* Destination in local link. */ 1655 destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; 1656 ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, destination_cache[nd6_cached_destination_index].destination_addr); 1657#ifdef LWIP_HOOK_ND6_GET_GW 1658 } else if ((next_hop_addr = LWIP_HOOK_ND6_GET_GW(netif, ip6addr)) != NULL) { 1659 /* Next hop for destination provided by hook function. */ 1660 destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; 1661 ip6_addr_set(&destination_cache[nd6_cached_destination_index].next_hop_addr, next_hop_addr); 1662#endif /* LWIP_HOOK_ND6_GET_GW */ 1663 } else { 1664 /* We need to select a router. */ 1665 i = nd6_select_router(ip6addr, netif); 1666 if (i < 0) { 1667 /* No router found. */ 1668 ip6_addr_set_any(&(destination_cache[nd6_cached_destination_index].destination_addr)); 1669 return ERR_RTE; 1670 } 1671 destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; /* Start with netif mtu, correct through ICMPv6 if necessary */ 1672 ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, default_router_list[i].neighbor_entry->next_hop_address); 1673 } 1674 } 1675 } 1676 1677#if LWIP_NETIF_HWADDRHINT 1678 if (netif->addr_hint != NULL) { 1679 /* per-pcb cached entry was given */ 1680 *(netif->addr_hint) = nd6_cached_destination_index; 1681 } 1682#endif /* LWIP_NETIF_HWADDRHINT */ 1683 1684 /* Look in neighbor cache for the next-hop address. */ 1685 if (ip6_addr_cmp(&(destination_cache[nd6_cached_destination_index].next_hop_addr), 1686 &(neighbor_cache[nd6_cached_neighbor_index].next_hop_address))) { 1687 /* Cache hit. */ 1688 /* Do nothing. */ 1689 ND6_STATS_INC(nd6.cachehit); 1690 } else { 1691 i = nd6_find_neighbor_cache_entry(&(destination_cache[nd6_cached_destination_index].next_hop_addr)); 1692 if (i >= 0) { 1693 /* Found a matching record, make it new cached entry. */ 1694 nd6_cached_neighbor_index = i; 1695 } else { 1696 /* Neighbor not in cache. Make a new entry. */ 1697 i = nd6_new_neighbor_cache_entry(); 1698 if (i >= 0) { 1699 /* got new neighbor entry. make it our new cached index. */ 1700 nd6_cached_neighbor_index = i; 1701 } else { 1702 /* Could not create a neighbor cache entry. */ 1703 return ERR_MEM; 1704 } 1705 1706 /* Initialize fields. */ 1707 ip6_addr_copy(neighbor_cache[i].next_hop_address, 1708 destination_cache[nd6_cached_destination_index].next_hop_addr); 1709 neighbor_cache[i].isrouter = 0; 1710 neighbor_cache[i].netif = netif; 1711 neighbor_cache[i].state = ND6_INCOMPLETE; 1712 neighbor_cache[i].counter.probes_sent = 1; 1713 nd6_send_neighbor_cache_probe(&neighbor_cache[i], ND6_SEND_FLAG_MULTICAST_DEST); 1714 } 1715 } 1716 1717 /* Reset this destination's age. */ 1718 destination_cache[nd6_cached_destination_index].age = 0; 1719 1720 return nd6_cached_neighbor_index; 1721} 1722 1723/** 1724 * Queue a packet for a neighbor. 1725 * 1726 * @param neighbor_index the index in the neighbor cache table 1727 * @param q packet to be queued 1728 * @return ERR_OK if succeeded, ERR_MEM if out of memory 1729 */ 1730static err_t 1731nd6_queue_packet(s8_t neighbor_index, struct pbuf *q) 1732{ 1733 err_t result = ERR_MEM; 1734 struct pbuf *p; 1735 int copy_needed = 0; 1736#if LWIP_ND6_QUEUEING 1737 struct nd6_q_entry *new_entry, *r; 1738#endif /* LWIP_ND6_QUEUEING */ 1739 1740 if ((neighbor_index < 0) || (neighbor_index >= LWIP_ND6_NUM_NEIGHBORS)) { 1741 return ERR_ARG; 1742 } 1743 1744 /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but 1745 * to copy the whole queue into a new PBUF_RAM (see bug #11400) 1746 * PBUF_ROMs can be left as they are, since ROM must not get changed. */ 1747 p = q; 1748 while (p) { 1749 if (p->type != PBUF_ROM) { 1750 copy_needed = 1; 1751 break; 1752 } 1753 p = p->next; 1754 } 1755 if (copy_needed) { 1756 /* copy the whole packet into new pbufs */ 1757 p = pbuf_alloc(PBUF_LINK, q->tot_len, PBUF_RAM); 1758 while ((p == NULL) && (neighbor_cache[neighbor_index].q != NULL)) { 1759 /* Free oldest packet (as per RFC recommendation) */ 1760#if LWIP_ND6_QUEUEING 1761 r = neighbor_cache[neighbor_index].q; 1762 neighbor_cache[neighbor_index].q = r->next; 1763 r->next = NULL; 1764 nd6_free_q(r); 1765#else /* LWIP_ND6_QUEUEING */ 1766 pbuf_free(neighbor_cache[neighbor_index].q); 1767 neighbor_cache[neighbor_index].q = NULL; 1768#endif /* LWIP_ND6_QUEUEING */ 1769 p = pbuf_alloc(PBUF_LINK, q->tot_len, PBUF_RAM); 1770 } 1771 if (p != NULL) { 1772 if (pbuf_copy(p, q) != ERR_OK) { 1773 pbuf_free(p); 1774 p = NULL; 1775 } 1776 } 1777 } else { 1778 /* referencing the old pbuf is enough */ 1779 p = q; 1780 pbuf_ref(p); 1781 } 1782 /* packet was copied/ref'd? */ 1783 if (p != NULL) { 1784 /* queue packet ... */ 1785#if LWIP_ND6_QUEUEING 1786 /* allocate a new nd6 queue entry */ 1787 new_entry = (struct nd6_q_entry *)memp_malloc(MEMP_ND6_QUEUE); 1788 if ((new_entry == NULL) && (neighbor_cache[neighbor_index].q != NULL)) { 1789 /* Free oldest packet (as per RFC recommendation) */ 1790 r = neighbor_cache[neighbor_index].q; 1791 neighbor_cache[neighbor_index].q = r->next; 1792 r->next = NULL; 1793 nd6_free_q(r); 1794 new_entry = (struct nd6_q_entry *)memp_malloc(MEMP_ND6_QUEUE); 1795 } 1796 if (new_entry != NULL) { 1797 new_entry->next = NULL; 1798 new_entry->p = p; 1799 if (neighbor_cache[neighbor_index].q != NULL) { 1800 /* queue was already existent, append the new entry to the end */ 1801 r = neighbor_cache[neighbor_index].q; 1802 while (r->next != NULL) { 1803 r = r->next; 1804 } 1805 r->next = new_entry; 1806 } else { 1807 /* queue did not exist, first item in queue */ 1808 neighbor_cache[neighbor_index].q = new_entry; 1809 } 1810 LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: queued packet %p on neighbor entry %"S16_F"\n", (void *)p, (s16_t)neighbor_index)); 1811 result = ERR_OK; 1812 } else { 1813 /* the pool MEMP_ND6_QUEUE is empty */ 1814 pbuf_free(p); 1815 LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: could not queue a copy of packet %p (out of memory)\n", (void *)p)); 1816 /* { result == ERR_MEM } through initialization */ 1817 } 1818#else /* LWIP_ND6_QUEUEING */ 1819 /* Queue a single packet. If an older packet is already queued, free it as per RFC. */ 1820 if (neighbor_cache[neighbor_index].q != NULL) { 1821 pbuf_free(neighbor_cache[neighbor_index].q); 1822 } 1823 neighbor_cache[neighbor_index].q = p; 1824 LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: queued packet %p on neighbor entry %"S16_F"\n", (void *)p, (s16_t)neighbor_index)); 1825 result = ERR_OK; 1826#endif /* LWIP_ND6_QUEUEING */ 1827 } else { 1828 LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: could not queue a copy of packet %p (out of memory)\n", (void *)q)); 1829 /* { result == ERR_MEM } through initialization */ 1830 } 1831 1832 return result; 1833} 1834 1835#if LWIP_ND6_QUEUEING 1836/** 1837 * Free a complete queue of nd6 q entries 1838 * 1839 * @param q a queue of nd6_q_entry to free 1840 */ 1841static void 1842nd6_free_q(struct nd6_q_entry *q) 1843{ 1844 struct nd6_q_entry *r; 1845 LWIP_ASSERT("q != NULL", q != NULL); 1846 LWIP_ASSERT("q->p != NULL", q->p != NULL); 1847 while (q) { 1848 r = q; 1849 q = q->next; 1850 LWIP_ASSERT("r->p != NULL", (r->p != NULL)); 1851 pbuf_free(r->p); 1852 memp_free(MEMP_ND6_QUEUE, r); 1853 } 1854} 1855#endif /* LWIP_ND6_QUEUEING */ 1856 1857/** 1858 * Send queued packets for a neighbor 1859 * 1860 * @param i the neighbor to send packets to 1861 */ 1862static void 1863nd6_send_q(s8_t i) 1864{ 1865 struct ip6_hdr *ip6hdr; 1866 ip6_addr_t dest; 1867#if LWIP_ND6_QUEUEING 1868 struct nd6_q_entry *q; 1869#endif /* LWIP_ND6_QUEUEING */ 1870 1871 if ((i < 0) || (i >= LWIP_ND6_NUM_NEIGHBORS)) { 1872 return; 1873 } 1874 1875#if LWIP_ND6_QUEUEING 1876 while (neighbor_cache[i].q != NULL) { 1877 /* remember first in queue */ 1878 q = neighbor_cache[i].q; 1879 /* pop first item off the queue */ 1880 neighbor_cache[i].q = q->next; 1881 /* Get ipv6 header. */ 1882 ip6hdr = (struct ip6_hdr *)(q->p->payload); 1883 /* Create an aligned copy. */ 1884 ip6_addr_set(&dest, &(ip6hdr->dest)); 1885 /* send the queued IPv6 packet */ 1886 (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, q->p, &dest); 1887 /* free the queued IP packet */ 1888 pbuf_free(q->p); 1889 /* now queue entry can be freed */ 1890 memp_free(MEMP_ND6_QUEUE, q); 1891 } 1892#else /* LWIP_ND6_QUEUEING */ 1893 if (neighbor_cache[i].q != NULL) { 1894 /* Get ipv6 header. */ 1895 ip6hdr = (struct ip6_hdr *)(neighbor_cache[i].q->payload); 1896 /* Create an aligned copy. */ 1897 ip6_addr_set(&dest, &(ip6hdr->dest)); 1898 /* send the queued IPv6 packet */ 1899 (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, neighbor_cache[i].q, &dest); 1900 /* free the queued IP packet */ 1901 pbuf_free(neighbor_cache[i].q); 1902 neighbor_cache[i].q = NULL; 1903 } 1904#endif /* LWIP_ND6_QUEUEING */ 1905} 1906 1907/** 1908 * A packet is to be transmitted to a specific IPv6 destination on a specific 1909 * interface. Check if we can find the hardware address of the next hop to use 1910 * for the packet. If so, give the hardware address to the caller, which should 1911 * use it to send the packet right away. Otherwise, enqueue the packet for 1912 * later transmission while looking up the hardware address, if possible. 1913 * 1914 * As such, this function returns one of three different possible results: 1915 * 1916 * - ERR_OK with a non-NULL 'hwaddrp': the caller should send the packet now. 1917 * - ERR_OK with a NULL 'hwaddrp': the packet has been enqueued for later. 1918 * - not ERR_OK: something went wrong; forward the error upward in the stack. 1919 * 1920 * @param netif The lwIP network interface on which the IP packet will be sent. 1921 * @param q The pbuf(s) containing the IP packet to be sent. 1922 * @param ip6addr The destination IPv6 address of the packet. 1923 * @param hwaddrp On success, filled with a pointer to a HW address or NULL (meaning 1924 * the packet has been queued). 1925 * @return 1926 * - ERR_OK on success, ERR_RTE if no route was found for the packet, 1927 * or ERR_MEM if low memory conditions prohibit sending the packet at all. 1928 */ 1929err_t 1930nd6_get_next_hop_addr_or_queue(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr, const u8_t **hwaddrp) 1931{ 1932 s8_t i; 1933 1934 /* Get next hop record. */ 1935 i = nd6_get_next_hop_entry(ip6addr, netif); 1936 if (i < 0) { 1937 /* failed to get a next hop neighbor record. */ 1938 return i; 1939 } 1940 1941 /* Now that we have a destination record, send or queue the packet. */ 1942 if (neighbor_cache[i].state == ND6_STALE) { 1943 /* Switch to delay state. */ 1944 neighbor_cache[i].state = ND6_DELAY; 1945 neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; 1946 } 1947 /* @todo should we send or queue if PROBE? send for now, to let unicast NS pass. */ 1948 if ((neighbor_cache[i].state == ND6_REACHABLE) || 1949 (neighbor_cache[i].state == ND6_DELAY) || 1950 (neighbor_cache[i].state == ND6_PROBE)) { 1951 1952 /* Tell the caller to send out the packet now. */ 1953 *hwaddrp = neighbor_cache[i].lladdr; 1954 return ERR_OK; 1955 } 1956 1957 /* We should queue packet on this interface. */ 1958 *hwaddrp = NULL; 1959 return nd6_queue_packet(i, q); 1960} 1961 1962 1963/** 1964 * Get the Path MTU for a destination. 1965 * 1966 * @param ip6addr the destination address 1967 * @param netif the netif on which the packet will be sent 1968 * @return the Path MTU, if known, or the netif default MTU 1969 */ 1970u16_t 1971nd6_get_destination_mtu(const ip6_addr_t *ip6addr, struct netif *netif) 1972{ 1973 s8_t i; 1974 1975 i = nd6_find_destination_cache_entry(ip6addr); 1976 if (i >= 0) { 1977 if (destination_cache[i].pmtu > 0) { 1978 return destination_cache[i].pmtu; 1979 } 1980 } 1981 1982 if (netif != NULL) { 1983 return netif->mtu; 1984 } 1985 1986 return 1280; /* Minimum MTU */ 1987} 1988 1989 1990#if LWIP_ND6_TCP_REACHABILITY_HINTS 1991/** 1992 * Provide the Neighbor discovery process with a hint that a 1993 * destination is reachable. Called by tcp_receive when ACKs are 1994 * received or sent (as per RFC). This is useful to avoid sending 1995 * NS messages every 30 seconds. 1996 * 1997 * @param ip6addr the destination address which is know to be reachable 1998 * by an upper layer protocol (TCP) 1999 */ 2000void 2001nd6_reachability_hint(const ip6_addr_t *ip6addr) 2002{ 2003 s8_t i; 2004 2005 /* Find destination in cache. */ 2006 if (ip6_addr_cmp(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) { 2007 i = nd6_cached_destination_index; 2008 ND6_STATS_INC(nd6.cachehit); 2009 } else { 2010 i = nd6_find_destination_cache_entry(ip6addr); 2011 } 2012 if (i < 0) { 2013 return; 2014 } 2015 2016 /* Find next hop neighbor in cache. */ 2017 if (ip6_addr_cmp(&(destination_cache[i].next_hop_addr), &(neighbor_cache[nd6_cached_neighbor_index].next_hop_address))) { 2018 i = nd6_cached_neighbor_index; 2019 ND6_STATS_INC(nd6.cachehit); 2020 } else { 2021 i = nd6_find_neighbor_cache_entry(&(destination_cache[i].next_hop_addr)); 2022 } 2023 if (i < 0) { 2024 return; 2025 } 2026 2027 /* For safety: don't set as reachable if we don't have a LL address yet. Misuse protection. */ 2028 if (neighbor_cache[i].state == ND6_INCOMPLETE || neighbor_cache[i].state == ND6_NO_ENTRY) { 2029 return; 2030 } 2031 2032 /* Set reachability state. */ 2033 neighbor_cache[i].state = ND6_REACHABLE; 2034 neighbor_cache[i].counter.reachable_time = reachable_time; 2035} 2036#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */ 2037 2038/** 2039 * Remove all prefix, neighbor_cache and router entries of the specified netif. 2040 * 2041 * @param netif points to a network interface 2042 */ 2043void 2044nd6_cleanup_netif(struct netif *netif) 2045{ 2046 u8_t i; 2047 s8_t router_index; 2048 for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { 2049 if (prefix_list[i].netif == netif) { 2050 prefix_list[i].netif = NULL; 2051 prefix_list[i].flags = 0; 2052 } 2053 } 2054 for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { 2055 if (neighbor_cache[i].netif == netif) { 2056 for (router_index = 0; router_index < LWIP_ND6_NUM_ROUTERS; router_index++) { 2057 if (default_router_list[router_index].neighbor_entry == &neighbor_cache[i]) { 2058 default_router_list[router_index].neighbor_entry = NULL; 2059 default_router_list[router_index].flags = 0; 2060 } 2061 } 2062 neighbor_cache[i].isrouter = 0; 2063 nd6_free_neighbor_cache_entry(i); 2064 } 2065 } 2066} 2067 2068#if LWIP_IPV6_MLD 2069/** 2070 * The state of a local IPv6 address entry is about to change. If needed, join 2071 * or leave the solicited-node multicast group for the address. 2072 * 2073 * @param netif The netif that owns the address. 2074 * @param addr_idx The index of the address. 2075 * @param new_state The new (IP6_ADDR_) state for the address. 2076 */ 2077void 2078nd6_adjust_mld_membership(struct netif *netif, s8_t addr_idx, u8_t new_state) 2079{ 2080 u8_t old_state, old_member, new_member; 2081 2082 old_state = netif_ip6_addr_state(netif, addr_idx); 2083 2084 /* Determine whether we were, and should be, a member of the solicited-node 2085 * multicast group for this address. For tentative addresses, the group is 2086 * not joined until the address enters the TENTATIVE_1 (or VALID) state. */ 2087 old_member = (old_state != IP6_ADDR_INVALID && old_state != IP6_ADDR_TENTATIVE); 2088 new_member = (new_state != IP6_ADDR_INVALID && new_state != IP6_ADDR_TENTATIVE); 2089 2090 if (old_member != new_member) { 2091 ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(netif, addr_idx)->addr[3]); 2092 2093 if (new_member) { 2094 mld6_joingroup_netif(netif, &multicast_address); 2095 } else { 2096 mld6_leavegroup_netif(netif, &multicast_address); 2097 } 2098 } 2099} 2100#endif /* LWIP_IPV6_MLD */ 2101 2102#endif /* LWIP_IPV6 */ 2103