UbixOS V2  2.0
nd6.c
Go to the documentation of this file.
1 
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 "net/opt.h"
45 
46 #if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
47 
48 #include "net/nd6.h"
49 #include "net/priv/nd6_priv.h"
50 #include "net/prot/nd6.h"
51 #include "net/prot/icmp6.h"
52 #include "net/pbuf.h"
53 #include "net/mem.h"
54 #include "net/memp.h"
55 #include "net/ip6.h"
56 #include "net/ip6_addr.h"
57 #include "net/inet_chksum.h"
58 #include "net/netif.h"
59 #include "net/icmp6.h"
60 #include "net/mld6.h"
61 #include "net/ip.h"
62 #include "net/stats.h"
63 #include "net/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. */
76 struct nd6_neighbor_cache_entry neighbor_cache[LWIP_ND6_NUM_NEIGHBORS];
77 struct nd6_destination_cache_entry destination_cache[LWIP_ND6_NUM_DESTINATIONS];
78 struct nd6_prefix_list_entry prefix_list[LWIP_ND6_NUM_PREFIXES];
79 struct nd6_router_list_entry default_router_list[LWIP_ND6_NUM_ROUTERS];
80 
81 /* Default values, can be updated by a RA message. */
82 u32_t reachable_time = LWIP_ND6_REACHABLE_TIME;
83 u32_t retrans_timer = LWIP_ND6_RETRANS_TIMER; /* @todo implement this value in timer */
84 
85 /* Index for cache entries. */
86 static u8_t nd6_cached_neighbor_index;
87 static u8_t nd6_cached_destination_index;
88 
89 /* Multicast address holder. */
90 static ip6_addr_t multicast_address;
91 
92 /* Static buffer to parse RA packet options (size of a prefix option, biggest option) */
93 static u8_t nd6_ra_buffer[sizeof(struct prefix_option)];
94 
95 /* Forward declarations. */
96 static s8_t nd6_find_neighbor_cache_entry(const ip6_addr_t *ip6addr);
97 static s8_t nd6_new_neighbor_cache_entry(void);
98 static void nd6_free_neighbor_cache_entry(s8_t i);
99 static s8_t nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr);
100 static s8_t nd6_new_destination_cache_entry(void);
101 static s8_t nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif);
102 static s8_t nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif);
103 static s8_t nd6_get_router(const ip6_addr_t *router_addr, struct netif *netif);
104 static s8_t nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif);
105 static s8_t nd6_get_onlink_prefix(ip6_addr_t *prefix, struct netif *netif);
106 static s8_t nd6_new_onlink_prefix(ip6_addr_t *prefix, struct netif *netif);
107 static s8_t nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif);
108 static 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
112 static void nd6_send_ns(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags);
113 static void nd6_send_na(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags);
114 static void nd6_send_neighbor_cache_probe(struct nd6_neighbor_cache_entry *entry, u8_t flags);
115 #if LWIP_IPV6_SEND_ROUTER_SOLICIT
116 static err_t nd6_send_rs(struct netif *netif);
117 #endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
118 
119 #if LWIP_ND6_QUEUEING
120 static 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 */
124 static void nd6_send_q(s8_t i);
125 
126 
133 void
134 nd6_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. */
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]) {
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  }
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  }
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
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 
715 void
716 nd6_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 
902 static void
903 nd6_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 
915 static void
916 nd6_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,
974  pbuf_free(p);
975 }
976 
984 static void
985 nd6_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,
1046  pbuf_free(p);
1047 }
1048 
1049 #if LWIP_IPV6_SEND_ROUTER_SOLICIT
1050 
1055 static err_t
1056 nd6_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,
1113  pbuf_free(p);
1114 
1115  return err;
1116 }
1117 #endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
1118 
1126 static s8_t
1127 nd6_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 
1147 static s8_t
1148 nd6_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 
1254 static void
1255 nd6_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 
1285 static s8_t
1286 nd6_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 
1304 static s8_t
1305 nd6_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 
1335 void
1336 nd6_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 
1351 static s8_t
1352 nd6_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 
1380 static s8_t
1381 nd6_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 
1441 struct netif *
1442 nd6_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 
1463 static s8_t
1464 nd6_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 
1488 static s8_t
1489 nd6_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 
1549 static s8_t
1550 nd6_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 
1573 static s8_t
1574 nd6_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 
1608 static s8_t
1609 nd6_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 
1730 static err_t
1731 nd6_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 */
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 */
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 
1841 static void
1842 nd6_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 
1862 static void
1863 nd6_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 
1929 err_t
1930 nd6_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 
1970 u16_t
1971 nd6_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 
2000 void
2001 nd6_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 
2043 void
2044 nd6_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 
2077 void
2078 nd6_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 */
DNS_MAX_SERVERS
#define DNS_MAX_SERVERS
Definition: lwipopts.h:160
S16_F
#define S16_F
Definition: arch.h:151
opt.h
ip_addr_cmp
#define ip_addr_cmp(addr1, addr2)
Definition: ip_addr.h:316
NETIF_FLAG_UP
#define NETIF_FLAG_UP
Definition: netif.h:86
pbuf::len
u16_t len
Definition: pbuf.h:159
rs_header
Definition: nd6.h:93
PBUF_LINK
Definition: pbuf.h:85
s16_t
int16_t s16_t
Definition: arch.h:125
ra_header
Definition: nd6.h:118
buffer
char * buffer
Definition: shell.c:47
ND6_PREFIX_FLAG_ON_LINK
#define ND6_PREFIX_FLAG_ON_LINK
Definition: nd6.h:172
nd6.h
LWIP_ASSERT
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:116
LWIP_ND6_DELAY_FIRST_PROBE_TIME
#define LWIP_ND6_DELAY_FIRST_PROBE_TIME
Definition: lwipopts.h:392
PBUF_ROM
Definition: pbuf.h:112
ICMP6_TYPE_RS
Definition: icmp6.h:74
pbuf.h
ND6_OPTION_TYPE_RDNSS
#define ND6_OPTION_TYPE_RDNSS
Definition: nd6.h:256
ERR_BUF
Definition: err.h:67
u16_t
uint16_t u16_t
Definition: arch.h:124
string.h
PBUF_IP
Definition: pbuf.h:80
pbuf::tot_len
u16_t tot_len
Definition: pbuf.h:156
LWIP_ND6_NUM_ROUTERS
#define LWIP_ND6_NUM_ROUTERS
Definition: lwipopts.h:384
ND6_STATS_INC
#define ND6_STATS_INC(x)
Definition: stats.h:460
u32_t
uint32_t u32_t
Definition: arch.h:126
netif::state
void * state
Definition: netif.h:287
LWIP_IPV6_SEND_ROUTER_SOLICIT
#define LWIP_IPV6_SEND_ROUTER_SOLICIT
Definition: lwipopts.h:371
ICMP6_TYPE_PTB
Definition: icmp6.h:51
pbuf::next
struct pbuf * next
Definition: pbuf.h:144
pbuf_free
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:715
redirect_header
Definition: nd6.h:139
ND6_OPTION_TYPE_TARGET_LLADDR
#define ND6_OPTION_TYPE_TARGET_LLADDR
Definition: nd6.h:155
netif::mtu
u16_t mtu
Definition: netif.h:307
memp_malloc
void * memp_malloc(memp_t type)
Definition: memp.c:385
LWIP_DBG_TRACE
#define LWIP_DBG_TRACE
Definition: debug.h:83
LWIP_ICMP6_HL
#define LWIP_ICMP6_HL
Definition: lwipopts.h:376
netif::flags
u8_t flags
Definition: netif.h:313
ND6_FLAG_OVERRIDE
#define ND6_FLAG_OVERRIDE
Definition: nd6.h:86
rdnss_option
Definition: nd6.h:261
LWIP_MIN
#define LWIP_MIN(x, y)
Definition: def.h:55
memp_free
void memp_free(memp_t type, void *mem)
Definition: memp.c:469
IF__NETIF_CHECKSUM_ENABLED
#define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag)
Definition: netif.h:357
htonl
#define htonl(x)
Definition: def.h:110
lladdr_option
Definition: nd6.h:160
stats.h
ERR_MEM
Definition: err.h:65
pbuf_copy_partial
u16_t pbuf_copy_partial(const struct pbuf *p, void *dataptr, u16_t len, u16_t offset)
Definition: pbuf.c:1016
icmp6.h
netif::hwaddr
u8_t hwaddr[6U]
Definition: netif.h:311
netif.h
LWIP_ND6_NUM_NEIGHBORS
#define LWIP_ND6_NUM_NEIGHBORS
Definition: lwipopts.h:381
mld6.h
ND6_FLAG_SOLICITED
#define ND6_FLAG_SOLICITED
Definition: nd6.h:85
pbuf_alloc
struct pbuf * pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type)
Definition: pbuf.c:248
ICMP6_TYPE_RA
Definition: icmp6.h:76
u8_t
uint8_t u8_t
Definition: arch.h:122
ip_addr_t
ip6_addr_t ip_addr_t
Definition: ip_addr.h:290
IP6_NEXTH_ICMP6
#define IP6_NEXTH_ICMP6
Definition: ip6.h:70
ICMP6_TYPE_RD
Definition: icmp6.h:82
ND6_PREFIX_FLAG_AUTONOMOUS
#define ND6_PREFIX_FLAG_AUTONOMOUS
Definition: nd6.h:173
nd6.h
netif
Definition: netif.h:233
ICMP6_TYPE_NS
Definition: icmp6.h:78
netif::hwaddr_len
u8_t hwaddr_len
Definition: netif.h:309
icmp6_hdr
Definition: icmp6.h:138
pbuf_copy
err_t pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from)
Definition: pbuf.c:949
ERR_ARG
Definition: err.h:96
lwip_htonl
u32_t lwip_htonl(u32_t n)
Definition: def.c:88
LWIP_IPV6_DUP_DETECT_ATTEMPTS
#define LWIP_IPV6_DUP_DETECT_ATTEMPTS
Definition: lwipopts.h:373
lwip_htons
u16_t lwip_htons(u16_t n)
Definition: def.c:75
netif::next
struct netif * next
Definition: netif.h:235
s8_t
int8_t s8_t
Definition: arch.h:123
pbuf_ref
void pbuf_ref(struct pbuf *p)
Definition: pbuf.c:821
PBUF_RAM
Definition: pbuf.h:108
netif_list
struct netif * netif_list
Definition: netif.c:104
mtu_option
Definition: nd6.h:220
ip_addr_copy_from_ip6
#define ip_addr_copy_from_ip6(dest, src)
Definition: ip_addr.h:306
icmp6.h
ERR_OK
Definition: err.h:63
err_t
s8_t err_t
Definition: err.h:57
ip.h
ND6_OPTION_TYPE_SOURCE_LLADDR
#define ND6_OPTION_TYPE_SOURCE_LLADDR
Definition: nd6.h:154
ND6_OPTION_TYPE_MTU
#define ND6_OPTION_TYPE_MTU
Definition: nd6.h:215
LWIP_ND6_NUM_PREFIXES
#define LWIP_ND6_NUM_PREFIXES
Definition: lwipopts.h:383
LWIP_ND6_RETRANS_TIMER
#define LWIP_ND6_RETRANS_TIMER
Definition: lwipopts.h:390
ns_header
Definition: nd6.h:53
IP6_HLEN
#define IP6_HLEN
Definition: ip6.h:62
LWIP_ND6_REACHABLE_TIME
#define LWIP_ND6_REACHABLE_TIME
Definition: lwipopts.h:389
na_header
Definition: nd6.h:71
ip6_addr.h
MEMCPY
#define MEMCPY(dst, src, len)
Definition: lwipopts.h:43
nd6_priv.h
prefix_option
Definition: nd6.h:180
ND6_OPTION_TYPE_ROUTE_INFO
#define ND6_OPTION_TYPE_ROUTE_INFO
Definition: nd6.h:232
memp.h
pbuf::type
u8_t type
Definition: pbuf.h:162
LWIP_ND6_NUM_DESTINATIONS
#define LWIP_ND6_NUM_DESTINATIONS
Definition: lwipopts.h:382
mem.h
ERR_RTE
Definition: err.h:71
SMEMCPY
#define SMEMCPY(dst, src, len)
Definition: lwipopts.h:44
dns.h
ip6_hdr
Definition: ip6.h:80
LWIP_ND6_MAX_MULTICAST_SOLICIT
#define LWIP_ND6_MAX_MULTICAST_SOLICIT
Definition: lwipopts.h:385
pbuf
Definition: pbuf.h:142
LWIP_DEBUGF
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:164
ip6.h
ICMP6_TYPE_NA
Definition: icmp6.h:80
inet_chksum.h
LWIP_IPV6_NUM_ADDRESSES
#define LWIP_IPV6_NUM_ADDRESSES
Definition: lwipopts.h:367
pbuf::payload
void * payload
Definition: pbuf.h:147
ND6_OPTION_TYPE_PREFIX_INFO
#define ND6_OPTION_TYPE_PREFIX_INFO
Definition: nd6.h:171
NULL
#define NULL
Definition: fat_string.h:17