ndp_misc.c
Go to the documentation of this file.
1 /**
2  * @file ndp_misc.c
3  * @brief Helper functions for NDP (Neighbor Discovery Protocol)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NDP_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "ipv6/ipv6.h"
37 #include "ipv6/ipv6_misc.h"
38 #include "ipv6/ndp.h"
39 #include "ipv6/ndp_cache.h"
40 #include "ipv6/ndp_misc.h"
41 #include "mdns/mdns_responder.h"
42 #include "debug.h"
43 
44 //Check TCP/IP stack configuration
45 #if (IPV6_SUPPORT == ENABLED && NDP_SUPPORT == ENABLED)
46 
47 
48 /**
49  * @brief Parse Prefix Information Option
50  * @param[in] interface Underlying network interface
51  * @param[in] option Pointer to the Prefix Information option
52  **/
53 
55 {
56  //Make sure the Prefix Information option is valid
57  if(option == NULL || option->length != 4)
58  return;
59 
60  //A prefix Information option that have the on-link flag set indicates a
61  //prefix identifying a range of addresses that should be considered on-link
62  if(!option->l)
63  return;
64 
65  //If the prefix is the link-local prefix, silently ignore the
66  //Prefix Information option
67  if(ipv6CompPrefix(&option->prefix, &IPV6_LINK_LOCAL_ADDR_PREFIX, 10))
68  return;
69 
70  //If the preferred lifetime is greater than the valid lifetime,
71  //silently ignore the Prefix Information option
72  if(ntohl(option->preferredLifetime) > ntohl(option->validLifetime))
73  return;
74 
75  //Check whether the Valid Lifetime field is non-zero
76  if(ntohl(option->validLifetime) != 0)
77  {
78  //If the prefix is not already present in the Prefix List, create a new
79  //entry for the prefix. If the prefix is already present in the list,
80  //reset its invalidation timer
81  ipv6AddPrefix(interface, &option->prefix, option->prefixLength, option->l,
82  option->a, ntohl(option->validLifetime), ntohl(option->preferredLifetime));
83  }
84  else
85  {
86  //If the new Lifetime value is zero, time-out the prefix immediately
87  ipv6RemovePrefix(interface, &option->prefix, option->prefixLength);
88  }
89 }
90 
91 
92 /**
93  * @brief Manage the lifetime of IPv6 addresses
94  * @param[in] interface Underlying network interface
95  **/
96 
98 {
99  uint_t i;
100  systime_t time;
101  Ipv6AddrEntry *entry;
102  NdpContext *context;
103 
104  //Point to the NDP context
105  context = &interface->ndpContext;
106 
107  //Get current time
108  time = osGetSystemTime();
109 
110  //Go through the list of IPv6 addresses
111  for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
112  {
113  //Point to the current entry
114  entry = &interface->ipv6Context.addrList[i];
115 
116  //Tentative address?
117  if(entry->state == IPV6_ADDR_STATE_TENTATIVE)
118  {
119  //Check whether the link is up
120  if(interface->linkState)
121  {
122  //To check an address, a node should send Neighbor Solicitation messages
123  if(entry->dadRetransmitCount == 0)
124  {
125  //Set time stamp
126  entry->timestamp = time;
127 
128  //Check whether Duplicate Address Detection should be performed
129  if(context->dupAddrDetectTransmits > 0)
130  {
131  //Link-local address?
132  if(i == 0)
133  {
134  //Delay before transmitting the first solicitation
135  entry->dadTimeout = netGenerateRandRange(0,
137 
138  //Prepare to send the first Neighbor Solicitation message
139  entry->dadRetransmitCount = 1;
140  }
141  else
142  {
143  //Valid link-local address?
145  {
146  //Prepare to send the first Neighbor Solicitation message
147  entry->dadTimeout = 0;
148  entry->dadRetransmitCount = 1;
149  }
150  }
151  }
152  else
153  {
154  //Do not perform Duplicate Address Detection
156  }
157  }
158  else
159  {
160  //Check current time
161  if(timeCompare(time, entry->timestamp + entry->dadTimeout) >= 0)
162  {
163  //Duplicate Address Detection failed?
164  if(entry->duplicate)
165  {
166  //A tentative address that is determined to be a duplicate
167  //must not be assigned to an interface
168  if(entry->permanent)
169  {
170  //The IPv6 address should be preserved if it has been
171  //manually assigned
172  ipv6SetAddr(interface, i, &entry->addr,
174  }
175  else
176  {
177  //The IPv6 address is no more valid and should be
178  //removed from the list
179  ipv6SetAddr(interface, i, &IPV6_UNSPECIFIED_ADDR,
181  }
182  }
183  //Duplicate Address Detection is on-going?
184  else if(entry->dadRetransmitCount <= context->dupAddrDetectTransmits)
185  {
186  //Send a multicast Neighbor Solicitation message
187  ndpSendNeighborSol(interface, &entry->addr, TRUE);
188 
189  //Set timeout value
190  entry->dadTimeout += context->retransTimer;
191  //Increment retransmission counter
192  entry->dadRetransmitCount++;
193  }
194  //Duplicate Address Detection is complete?
195  else
196  {
197  //The use of the IPv6 address is now unrestricted
199 
200 #if (MDNS_RESPONDER_SUPPORT == ENABLED)
201  //Restart mDNS probing process
202  mdnsResponderStartProbing(interface->mdnsResponderContext);
203 #endif
204  }
205  }
206  }
207  }
208  }
209  //Preferred address?
210  else if(entry->state == IPV6_ADDR_STATE_PREFERRED)
211  {
212  //An IPv6 address with an infinite preferred lifetime is never timed out
214  {
215  //When the preferred lifetime expires, the address becomes deprecated
216  if(timeCompare(time, entry->timestamp + entry->preferredLifetime) >= 0)
217  {
218  //A deprecated address should continue to be used as a source
219  //address in existing communications, but should not be used
220  //to initiate new communications
222  }
223  }
224  }
225  //Deprecated address?
226  else if(entry->state == IPV6_ADDR_STATE_DEPRECATED)
227  {
228  //An IPv6 address with an infinite valid lifetime is never timed out
230  {
231  //When the valid lifetime expires, the address becomes invalid
232  if(timeCompare(time, entry->timestamp + entry->validLifetime) >= 0)
233  {
234  //The IPv6 address is no more valid and should be removed from the list
235  ipv6SetAddr(interface, i, &IPV6_UNSPECIFIED_ADDR,
237  }
238  }
239  }
240  }
241 }
242 
243 
244 /**
245  * @brief Periodically update Prefix List
246  * @param[in] interface Underlying network interface
247  **/
248 
250 {
251  uint_t i;
252  systime_t time;
253  Ipv6PrefixEntry *entry;
254 
255  //Get current time
256  time = osGetSystemTime();
257 
258  //Go through the Prefix List
259  for(i = 0; i < IPV6_PREFIX_LIST_SIZE; i++)
260  {
261  //Point to the current entry
262  entry = &interface->ipv6Context.prefixList[i];
263 
264  //Check the lifetime value
265  if(entry->validLifetime > 0 && entry->validLifetime < INFINITE_DELAY)
266  {
267  //A node should retain entries in the Prefix List until their
268  //lifetimes expire
269  if(timeCompare(time, entry->timestamp + entry->validLifetime) >= 0)
270  {
271  //When removing an entry from the Prefix List, there is no need
272  //to purge any entries from the Destination or Neighbor Caches
273  ipv6RemovePrefix(interface, &entry->prefix, entry->prefixLen);
274  }
275  }
276  }
277 }
278 
279 
280 /**
281  * @brief Periodically update Default Router List
282  * @param[in] interface Underlying network interface
283  **/
284 
286 {
287  uint_t i;
288  bool_t flag;
289  systime_t time;
290  Ipv6RouterEntry *entry;
291 
292  //This flag will be set if any entry has been removed from
293  //the Default Router List
294  flag = FALSE;
295 
296  //Get current time
297  time = osGetSystemTime();
298 
299  //Go through the Default Router List
300  for(i = 0; i < IPV6_ROUTER_LIST_SIZE; i++)
301  {
302  //Point to the current entry
303  entry = &interface->ipv6Context.routerList[i];
304 
305  //Check the lifetime value
306  if(entry->lifetime > 0 && entry->lifetime < INFINITE_DELAY)
307  {
308  //A node should retain entries in the Default Router List until
309  //their lifetimes expire
310  if(timeCompare(time, entry->timestamp + entry->lifetime) >= 0)
311  {
312  //Immediately time-out the entry
313  entry->addr = IPV6_UNSPECIFIED_ADDR;
314  entry->lifetime = 0;
315 
316  //Set flag
317  flag = TRUE;
318  }
319  }
320  }
321 
322  //Check whether an entry has been removed from the list
323  if(flag)
324  {
325  //When removing an entry from the Default Router List, any entries
326  //in the Destination Cache that go through that router must perform
327  //next-hop determination again to select a new default router
328  ndpFlushDestCache(interface);
329  }
330 }
331 
332 
333 /**
334  * @brief Default Router Selection
335  * @param[in] interface Underlying network interface
336  * @param[in] unreachableAddr IPv6 address of the unreachable router (optional parameter)
337  * @param[out] addr IPv6 address of the default router to be used
338  * @return Error code
339  **/
340 
342  const Ipv6Addr *unreachableAddr, Ipv6Addr *addr)
343 {
344  uint_t i;
345  uint_t j;
346  uint_t k;
347  Ipv6RouterEntry *routerEntry;
348  NdpNeighborCacheEntry *neighborCacheEntry;
349 
350  //Initialize index
351  i = 0;
352 
353  //This parameter is optional...
354  if(unreachableAddr != NULL)
355  {
356  //Search the Default Router List for the router whose reachability is suspect
357  for(j = 0; j < IPV6_ROUTER_LIST_SIZE; j++)
358  {
359  //Point to the current entry
360  routerEntry = &interface->ipv6Context.routerList[j];
361 
362  //Check the lifetime associated with the default router
363  if(routerEntry->lifetime)
364  {
365  //Check the router address against the address whose reachability is suspect
366  if(ipv6CompAddr(&routerEntry->addr, unreachableAddr))
367  {
368  //Routers should be selected in a round-robin fashion
369  i = j + 1;
370  //We are done
371  break;
372  }
373  }
374  }
375  }
376 
377  //Routers that are reachable or probably reachable should be preferred
378  //over routers whose reachability is unknown or suspect
379  for(j = 0; j < IPV6_ROUTER_LIST_SIZE; j++)
380  {
381  //Get current index
382  k = (i + j) % IPV6_ROUTER_LIST_SIZE;
383 
384  //Point to the corresponding entry
385  routerEntry = &interface->ipv6Context.routerList[k];
386 
387  //Check the lifetime associated with the default router
388  if(routerEntry->lifetime)
389  {
390  //Search the Neighbor Cache for the router address
391  neighborCacheEntry = ndpFindNeighborCacheEntry(interface, &routerEntry->addr);
392 
393  //Check whether the router is reachable or probably reachable
394  if(neighborCacheEntry != NULL)
395  {
396  //Any state other than INCOMPLETE?
397  if(neighborCacheEntry->state != NDP_STATE_INCOMPLETE)
398  {
399  //Return the IPv6 address of the default router
400  *addr = routerEntry->addr;
401  //Successful default router selection
402  return NO_ERROR;
403  }
404  }
405  }
406  }
407 
408  //When no routers on the list are known to be reachable or probably
409  //reachable, routers should be selected in a round-robin fashion, so
410  //that subsequent requests for a default router do not return the
411  //same router until all other routers have been selected
412  for(j = 0; j < IPV6_ROUTER_LIST_SIZE; j++)
413  {
414  //Get current index
415  k = (i + j) % IPV6_ROUTER_LIST_SIZE;
416 
417  //Point to the corresponding entry
418  routerEntry = &interface->ipv6Context.routerList[k];
419 
420  //Check the lifetime associated with the default router
421  if(routerEntry->lifetime)
422  {
423  //Return the IPv6 address of the default router
424  *addr = routerEntry->addr;
425  //Successful default router selection
426  return NO_ERROR;
427  }
428  }
429 
430  //No default router found
431  return ERROR_NO_ROUTE;
432 }
433 
434 
435 /**
436  * @brief Check whether an address is the first-hop router for the specified destination
437  * @param[in] interface Underlying network interface
438  * @param[in] destAddr Destination address
439  * @param[in] nextHop First-hop address to be checked
440  * @return TRUE if the address is the first-hop router, else FALSE
441  **/
442 
444  const Ipv6Addr *destAddr, const Ipv6Addr *nextHop)
445 {
446  uint_t i;
447  bool_t isFirstHopRouter;
448  Ipv6RouterEntry *routerEntry;
449  NdpDestCacheEntry *destCacheEntry;
450 
451  //Clear flag
452  isFirstHopRouter = FALSE;
453 
454  //Search the cache for the specified destination address
455  destCacheEntry = ndpFindDestCacheEntry(interface, destAddr);
456 
457  //Any matching entry?
458  if(destCacheEntry != NULL)
459  {
460  //Check if the address is the same as the current first-hop
461  //router for the specified destination
462  if(ipv6CompAddr(&destCacheEntry->nextHop, nextHop))
463  isFirstHopRouter = TRUE;
464  }
465  else
466  {
467  //Loop through the Default Router List
468  for(i = 0; i < IPV6_ROUTER_LIST_SIZE; i++)
469  {
470  //Point to the current entry
471  routerEntry = &interface->ipv6Context.routerList[i];
472 
473  //Check the lifetime associated with the default router
474  if(routerEntry->lifetime)
475  {
476  //Check whether the current entry matches the specified address
477  if(ipv6CompAddr(&routerEntry->addr, nextHop))
478  {
479  //The specified address is a valid first-hop router
480  isFirstHopRouter = TRUE;
481  //We are done
482  break;
483  }
484  }
485  }
486  }
487 
488  //Return TRUE if the address is the same as the current first-hop
489  //router for the specified destination
490  return isFirstHopRouter;
491 }
492 
493 
494 /**
495  * @brief Next-hop determination
496  * @param[in] interface Underlying network interface
497  * @param[in] destAddr Destination address
498  * @param[in] unreachableNextHop Address of the unreachable next-hop (optional
499  * parameter)
500  * @param[out] nextHop Next-hop address to be used
501  * @param[in] dontRoute Do not send the packet via a router
502  * @return Error code
503  **/
504 
506  const Ipv6Addr *unreachableNextHop, Ipv6Addr *nextHop, bool_t dontRoute)
507 {
508  error_t error;
509 
510  //Initialize status code
511  error = NO_ERROR;
512 
513  //Destination IPv6 address is a multicast address?
515  {
516  //For multicast packets, the next-hop is always the multicast destination
517  //address and is considered to be on-link
518  *nextHop = *destAddr;
519  }
520  else
521  {
522  //The sender performs a longest prefix match against the Prefix List to
523  //determine whether the packet's destination is on-link or off-link
524  if(ipv6IsOnLink(interface, destAddr))
525  {
526  //If the destination is on-link, the next-hop address is the same as
527  //the packet's destination address
528  *nextHop = *destAddr;
529  }
530  else if(dontRoute)
531  {
532  //Do not send the packet via a router
533  *nextHop = *destAddr;
534  }
535  else
536  {
537  //If the destination is off-link, the sender selects a router from
538  //the Default Router List
539  error = ndpSelectDefaultRouter(interface, unreachableNextHop, nextHop);
540  }
541  }
542 
543  //Return status code
544  return error;
545 }
546 
547 
548 /**
549  * @brief Update next-hop field of Destination Cache entries
550  * @param[in] interface Underlying network interface
551  * @param[in] unreachableNextHop Address of the unreachable next-hop
552  **/
553 
554 void ndpUpdateNextHop(NetInterface *interface, const Ipv6Addr *unreachableNextHop)
555 {
556  error_t error;
557  uint_t i;
558  NdpDestCacheEntry *entry;
559 
560  //Go through Destination Cache
561  for(i = 0; i < NDP_DEST_CACHE_SIZE; i++)
562  {
563  //Point to the current entry
564  entry = &interface->ndpContext.destCache[i];
565 
566  //Check whether the unreachable IPv6 address is used a first-hop router
567  if(ipv6CompAddr(&entry->nextHop, unreachableNextHop))
568  {
569  //Perform next-hop determination
570  error = ndpSelectNextHop(interface, &entry->destAddr, &entry->nextHop,
571  &entry->nextHop, FALSE);
572 
573  //Next-hop determination failed?
574  if(error)
575  {
576  //Remove the current entry from the Destination Cache
578  }
579  }
580  }
581 }
582 
583 
584 /**
585  * @brief Append an option to a NDP message
586  * @param[in] message Pointer to the NDP message
587  * @param[in,out] messageLen Length of the entire message
588  * @param[in] type Option type
589  * @param[in] value Option value
590  * @param[in] length Length of the option value
591  **/
592 
593 void ndpAddOption(void *message, size_t *messageLen, uint8_t type,
594  const void *value, size_t length)
595 {
596  size_t optionLen;
597  size_t paddingLen;
598  NdpOption *option;
599 
600  //Length of the option in units of 8 bytes including the type and length fields
601  optionLen = (length + sizeof(NdpOption) + 7) / 8;
602 
603  //Sanity check
604  if(optionLen <= UINT8_MAX)
605  {
606  //Point to the buffer where the option is to be written
607  option = (NdpOption *) ((uint8_t *) message + *messageLen);
608 
609  //Option type
610  option->type = type;
611  //Option length
612  option->length = (uint8_t) optionLen;
613  //Option value
614  osMemcpy(option->value, value, length);
615 
616  //Options should be padded when necessary to ensure that they end on
617  //their natural 64-bit boundaries
618  if((length + sizeof(NdpOption)) < (optionLen * 8))
619  {
620  //Determine the amount of padding data to append
621  paddingLen = (optionLen * 8) - length - sizeof(NdpOption);
622  //Write padding data
623  osMemset(option->value + length, 0, paddingLen);
624  }
625 
626  //Adjust the length of the NDP message
627  *messageLen += optionLen * 8;
628  }
629 }
630 
631 
632 /**
633  * @brief Search a NDP message for a given option
634  * @param[in] options Pointer to the Options field
635  * @param[in] length Length of the Options field
636  * @param[in] type Type of the option to find
637  * @return If the specified option is found, a pointer to the corresponding
638  * option is returned. Otherwise NULL pointer is returned
639  **/
640 
641 void *ndpGetOption(uint8_t *options, size_t length, uint8_t type)
642 {
643  size_t i;
644  NdpOption *option;
645 
646  //Point to the very first option of the NDP message
647  i = 0;
648 
649  //Parse options
650  while((i + sizeof(NdpOption)) <= length)
651  {
652  //Point to the current option
653  option = (NdpOption *) (options + i);
654 
655  //Nodes must silently discard an NDP message that contains
656  //an option with length zero
657  if(option->length == 0)
658  break;
659  //Check option length
660  if((i + option->length * 8) > length)
661  break;
662 
663  //Current option type matches the specified one?
664  if(option->type == type || type == NDP_OPT_ANY)
665  return option;
666 
667  //Jump to the next option
668  i += option->length * 8;
669  }
670 
671  //The specified option type was not found
672  return NULL;
673 }
674 
675 
676 /**
677  * @brief Check NDP message options
678  * @param[in] options Pointer to the Options field
679  * @param[in] length Length of the Options field
680  * @return Error code
681  **/
682 
683 error_t ndpCheckOptions(const uint8_t *options, size_t length)
684 {
685  size_t i;
686  NdpOption *option;
687 
688  //Point to the very first option of the NDP message
689  i = 0;
690 
691  //Parse options
692  while((i + sizeof(NdpOption)) <= length)
693  {
694  //Point to the current option
695  option = (NdpOption *) (options + i);
696 
697  //Nodes must silently discard an NDP message that contains
698  //an option with length zero
699  if(option->length == 0)
700  return ERROR_INVALID_OPTION;
701 
702  //Jump to the next option
703  i += option->length * 8;
704  }
705 
706  //The Options field is valid
707  return NO_ERROR;
708 }
709 
710 #endif
uint8_t message[]
Definition: chap.h:154
uint8_t type
Definition: coap_common.h:176
unsigned int uint_t
Definition: compiler_port.h:50
int bool_t
Definition: compiler_port.h:53
#define ntohl(value)
Definition: cpu_endian.h:422
Debugging facilities.
uint32_t time
error_t
Error codes.
Definition: error.h:43
@ ERROR_INVALID_OPTION
Definition: error.h:98
@ ERROR_NO_ROUTE
Definition: error.h:219
@ NO_ERROR
Success.
Definition: error.h:44
Ipv4Addr destAddr
Definition: ipv4.h:299
const Ipv6Addr IPV6_LINK_LOCAL_ADDR_PREFIX
Definition: ipv6.c:81
const Ipv6Addr IPV6_UNSPECIFIED_ADDR
Definition: ipv6.c:65
Ipv6AddrState ipv6GetLinkLocalAddrState(NetInterface *interface)
Get the state of the link-local address.
Definition: ipv6.c:326
IPv6 (Internet Protocol Version 6)
Ipv6Addr
Definition: ipv6.h:251
#define ipv6IsMulticastAddr(ipAddr)
Definition: ipv6.h:132
#define IPV6_PREFIX_LIST_SIZE
Definition: ipv6.h:79
#define IPV6_ADDR_LIST_SIZE
Definition: ipv6.h:65
#define ipv6CompAddr(ipAddr1, ipAddr2)
Definition: ipv6.h:120
@ IPV6_ADDR_STATE_DEPRECATED
An address assigned to an interface whose use is discouraged.
Definition: ipv6.h:169
@ IPV6_ADDR_STATE_PREFERRED
An address assigned to an interface whose use is unrestricted.
Definition: ipv6.h:168
@ IPV6_ADDR_STATE_INVALID
An address that is not assigned to any interface.
Definition: ipv6.h:166
@ IPV6_ADDR_STATE_TENTATIVE
An address whose uniqueness on a link is being verified.
Definition: ipv6.h:167
#define IPV6_ROUTER_LIST_SIZE
Definition: ipv6.h:86
error_t ipv6SetAddr(NetInterface *interface, uint_t index, const Ipv6Addr *addr, Ipv6AddrState state, systime_t validLifetime, systime_t preferredLifetime, bool_t permanent)
Set IPv6 address and address state.
Definition: ipv6_misc.c:95
bool_t ipv6CompPrefix(const Ipv6Addr *ipAddr1, const Ipv6Addr *ipAddr2, size_t length)
Compare IPv6 address prefixes.
Definition: ipv6_misc.c:1221
void ipv6AddPrefix(NetInterface *interface, const Ipv6Addr *prefix, uint_t length, bool_t onLinkFlag, bool_t autonomousFlag, uint32_t validLifetime, uint32_t preferredLifetime)
Add a new entry to the Prefix List.
Definition: ipv6_misc.c:379
bool_t ipv6IsOnLink(NetInterface *interface, const Ipv6Addr *ipAddr)
Check whether an IPv6 address is on-link.
Definition: ipv6_misc.c:1045
void ipv6RemovePrefix(NetInterface *interface, const Ipv6Addr *prefix, uint_t length)
Remove an entry from the Prefix List.
Definition: ipv6_misc.c:492
Helper functions for IPv6.
error_t mdnsResponderStartProbing(MdnsResponderContext *context)
Restart probing process.
mDNS responder (Multicast DNS)
Ipv4Addr addr
Definition: nbns_common.h:123
error_t ndpSendNeighborSol(NetInterface *interface, const Ipv6Addr *targetIpAddr, bool_t multicast)
Send a Neighbor Solicitation message.
Definition: ndp.c:1689
NDP (Neighbor Discovery Protocol)
#define NDP_DEST_CACHE_SIZE
Definition: ndp.h:60
#define NDP_INFINITE_LIFETIME
Definition: ndp.h:202
@ NDP_STATE_INCOMPLETE
Definition: ndp.h:250
NdpOption
Definition: ndp.h:379
NdpPrefixInfoOption
Definition: ndp.h:418
#define NDP_MAX_RTR_SOLICITATION_DELAY
Definition: ndp.h:123
@ NDP_OPT_ANY
Definition: ndp.h:226
void ndpFlushDestCache(NetInterface *interface)
Flush Destination Cache.
Definition: ndp_cache.c:532
NdpNeighborCacheEntry * ndpFindNeighborCacheEntry(NetInterface *interface, const Ipv6Addr *ipAddr)
Search the Neighbor cache for a given IPv6 address.
Definition: ndp_cache.c:154
NdpDestCacheEntry * ndpFindDestCacheEntry(NetInterface *interface, const Ipv6Addr *destAddr)
Search the Destination Cache for a given destination address.
Definition: ndp_cache.c:503
Neighbor and destination cache management.
void ndpUpdateDefaultRouterList(NetInterface *interface)
Periodically update Default Router List.
Definition: ndp_misc.c:285
void ndpUpdateAddrList(NetInterface *interface)
Manage the lifetime of IPv6 addresses.
Definition: ndp_misc.c:97
void ndpAddOption(void *message, size_t *messageLen, uint8_t type, const void *value, size_t length)
Append an option to a NDP message.
Definition: ndp_misc.c:593
void ndpUpdatePrefixList(NetInterface *interface)
Periodically update Prefix List.
Definition: ndp_misc.c:249
void ndpUpdateNextHop(NetInterface *interface, const Ipv6Addr *unreachableNextHop)
Update next-hop field of Destination Cache entries.
Definition: ndp_misc.c:554
void * ndpGetOption(uint8_t *options, size_t length, uint8_t type)
Search a NDP message for a given option.
Definition: ndp_misc.c:641
error_t ndpSelectNextHop(NetInterface *interface, const Ipv6Addr *destAddr, const Ipv6Addr *unreachableNextHop, Ipv6Addr *nextHop, bool_t dontRoute)
Next-hop determination.
Definition: ndp_misc.c:505
error_t ndpCheckOptions(const uint8_t *options, size_t length)
Check NDP message options.
Definition: ndp_misc.c:683
error_t ndpSelectDefaultRouter(NetInterface *interface, const Ipv6Addr *unreachableAddr, Ipv6Addr *addr)
Default Router Selection.
Definition: ndp_misc.c:341
bool_t ndpIsFirstHopRouter(NetInterface *interface, const Ipv6Addr *destAddr, const Ipv6Addr *nextHop)
Check whether an address is the first-hop router for the specified destination.
Definition: ndp_misc.c:443
void ndpParsePrefixInfoOption(NetInterface *interface, NdpPrefixInfoOption *option)
Parse Prefix Information Option.
Definition: ndp_misc.c:54
Helper functions for NDP (Neighbor Discovery Protocol)
TCP/IP stack core.
#define NetInterface
Definition: net.h:36
uint32_t netGenerateRandRange(uint32_t min, uint32_t max)
Generate a random value in the specified range.
Definition: net_misc.c:914
#define osMemset(p, value, length)
Definition: os_port.h:135
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
#define timeCompare(t1, t2)
Definition: os_port.h:40
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
#define INFINITE_DELAY
Definition: os_port.h:75
systime_t osGetSystemTime(void)
Retrieve system time.
uint32_t systime_t
System time.
IPv6 address entry.
Definition: ipv6.h:399
systime_t timestamp
Timestamp to manage entry lifetime.
Definition: ipv6.h:406
bool_t permanent
Permanently assigned address.
Definition: ipv6.h:405
bool_t duplicate
The address is a duplicate.
Definition: ipv6.h:402
Ipv6AddrState state
IPv6 address state.
Definition: ipv6.h:401
systime_t preferredLifetime
Preferred lifetime.
Definition: ipv6.h:404
systime_t validLifetime
Valid lifetime.
Definition: ipv6.h:403
uint_t dadRetransmitCount
Retransmission counter for Duplicate Address Detection.
Definition: ipv6.h:408
systime_t dadTimeout
Timeout value for Duplicate Address Detection.
Definition: ipv6.h:407
Ipv6Addr addr
IPv6 address.
Definition: ipv6.h:400
Prefix list entry.
Definition: ipv6.h:417
systime_t timestamp
Timestamp to manage entry lifetime.
Definition: ipv6.h:425
systime_t validLifetime
Valid lifetime.
Definition: ipv6.h:422
Ipv6Addr prefix
IPv6 prefix information.
Definition: ipv6.h:418
uint8_t prefixLen
IPv6 prefix length.
Definition: ipv6.h:419
Default router list entry.
Definition: ipv6.h:434
systime_t timestamp
Timestamp to manage entry lifetime.
Definition: ipv6.h:439
systime_t lifetime
Router lifetime.
Definition: ipv6.h:436
Ipv6Addr addr
Router address.
Definition: ipv6.h:435
NDP context.
Definition: ndp.h:580
uint_t dupAddrDetectTransmits
Maximum number of NS messages sent while performing DAD.
Definition: ndp.h:583
uint32_t retransTimer
The time between retransmissions of NS messages.
Definition: ndp.h:582
Destination cache entry.
Definition: ndp.h:567
Ipv6Addr nextHop
IPv6 address of the next-hop neighbor.
Definition: ndp.h:569
Ipv6Addr destAddr
Destination IPv6 address.
Definition: ndp.h:568
Neighbor cache entry.
Definition: ndp.h:549
NdpState state
Reachability state.
Definition: ndp.h:550
uint8_t length
Definition: tcp.h:368
uint8_t value[]
Definition: tcp.h:369
uint8_t options[]
Definition: tcp.h:357