ndp.c
Go to the documentation of this file.
1 /**
2  * @file ndp.c
3  * @brief NDP (Neighbor Discovery Protocol)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 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  * @section Description
28  *
29  * The Neighbor Discovery Protocol is responsible for address autoconfiguration
30  * of nodes, discovery of the link-layer addresses of other nodes, duplicate
31  * address detection, finding available routers and address prefix discovery.
32  * Refer to RFC 4861 for more details
33  *
34  * @author Oryx Embedded SARL (www.oryx-embedded.com)
35  * @version 2.5.0
36  **/
37 
38 //Switch to the appropriate trace level
39 #define TRACE_LEVEL NDP_TRACE_LEVEL
40 
41 //Dependencies
42 #include <limits.h>
43 #include "core/net.h"
44 #include "ipv6/ipv6.h"
45 #include "ipv6/ipv6_misc.h"
46 #include "ipv6/icmpv6.h"
47 #include "ipv6/ndp.h"
48 #include "ipv6/ndp_cache.h"
49 #include "ipv6/ndp_misc.h"
50 #include "ipv6/slaac.h"
51 #include "ipv6/slaac_misc.h"
52 #include "mibs/ip_mib_module.h"
53 #include "debug.h"
54 
55 //Check TCP/IP stack configuration
56 #if (IPV6_SUPPORT == ENABLED && NDP_SUPPORT == ENABLED)
57 
58 //Tick counter to handle periodic operations
60 
61 
62 /**
63  * @brief Neighbor cache initialization
64  * @param[in] interface Underlying network interface
65  * @return Error code
66  **/
67 
69 {
70  NdpContext *context;
71 
72  //Point to the NDP context
73  context = &interface->ndpContext;
74 
75  //Clear the NDP context
76  osMemset(context, 0, sizeof(NdpContext));
77 
78  //Initialize interface specific variables
86 
87  //Enable Neighbor Discovery protocol
88  context->enable = TRUE;
89 
90  //Successful initialization
91  return NO_ERROR;
92 }
93 
94 
95 /**
96  * @brief Enable address resolution using Neighbor Discovery protocol
97  * @param[in] interface Underlying network interface
98  * @param[in] enable This flag specifies whether the host is allowed to send
99  * Neighbor solicitations and respond to incoming Neighbor solicitations.
100  * When the flag is set to FALSE, the host relies exclusively on static
101  * Neighbor cache entries to map IPv6 addresses into MAC addresses and
102  * silently drop incoming Neighbor solicitations
103  * @return Error code
104  **/
105 
107 {
108  //Check parameters
109  if(interface == NULL)
111 
112  //Get exclusive access
114 
115  //Enable or disable Neighbor Discovery protocol
116  interface->ndpContext.enable = enable;
117 
118  //If Neighbor Discovery protocol is disabled then flush dynamic entries
119  //from the Neighbor cache
120  if(!enable)
121  {
122  ndpFlushNeighborCache(interface);
123  }
124 
125  //Release exclusive access
127 
128  //Successful processing
129  return NO_ERROR;
130 }
131 
132 
133 /**
134  * @brief Configure the NDP reachable time
135  * @param[in] interface Underlying network interface
136  * @param[in] reachableTime The time, in milliseconds, a node assumes a
137  * neighbor is reachable
138  * @return Error code
139  **/
140 
142 {
143  uint_t i;
144  NdpNeighborCacheEntry *entry;
145 
146  //Check parameters
147  if(interface == NULL || reachableTime == 0)
149 
150  //Get exclusive access
152 
153  //Save reachable time
154  interface->ndpContext.reachableTime = reachableTime;
155 
156  //Loop through Neighbor cache entries
157  for(i = 0; i < NDP_NEIGHBOR_CACHE_SIZE; i++)
158  {
159  //Point to the current entry
160  entry = &interface->ndpContext.neighborCache[i];
161 
162  //Check the state of the Neighbor cache entry
163  if(entry->state == NDP_STATE_REACHABLE)
164  {
165  //Adjust the reachable time, if necessary
166  if(entry->timeout > reachableTime)
167  {
168  entry->timeout = reachableTime;
169  }
170  }
171  }
172 
173  //Release exclusive access
175 
176  //Successful processing
177  return NO_ERROR;
178 }
179 
180 
181 /**
182  * @brief Configure the time interval between retransmission of NS messages
183  * @param[in] interface Underlying network interface
184  * @param[in] retransTimer The time, in milliseconds, between retransmissions
185  * of NS messages
186  * @return Error code
187  **/
188 
190 {
191  uint_t i;
192  NdpNeighborCacheEntry *entry;
193 
194  //Check parameters
195  if(interface == NULL || retransTimer == 0)
197 
198  //Get exclusive access
200 
201  //Save retransmission time
202  interface->ndpContext.retransTimer = retransTimer;
203 
204  //Loop through Neighbor cache entries
205  for(i = 0; i < NDP_NEIGHBOR_CACHE_SIZE; i++)
206  {
207  //Point to the current entry
208  entry = &interface->ndpContext.neighborCache[i];
209 
210  //Check the state of the Neighbor cache entry
211  if(entry->state == NDP_STATE_INCOMPLETE ||
212  entry->state == NDP_STATE_PROBE)
213  {
214  //Adjust the reachable time, if necessary
215  if(entry->timeout > retransTimer)
216  {
217  entry->timeout = retransTimer;
218  }
219  }
220  }
221 
222  //Release exclusive access
224 
225  //Successful processing
226  return NO_ERROR;
227 }
228 
229 
230 /**
231  * @brief Add a static entry in the Neighbor cache
232  * @param[in] interface Underlying network interface
233  * @param[in] ipAddr IPv6 address
234  * @param[in] macAddr MAC address
235  * @return Error code
236  **/
237 
239  const MacAddr *macAddr)
240 {
241  error_t error;
242  NdpNeighborCacheEntry *entry;
243 
244  //Check parameters
245  if(interface == NULL || ipAddr == NULL || macAddr == NULL)
247 
248  //Get exclusive access
250 
251  //Search the Neighbor cache for the specified IPv6 address
252  entry = ndpFindNeighborCacheEntry(interface, ipAddr);
253 
254  //Check whether a matching entry exists
255  if(entry != NULL)
256  {
257  //Check the state of the Neighbor cache entry
258  if(entry->state == NDP_STATE_INCOMPLETE)
259  {
260  //Record the corresponding MAC address
261  entry->macAddr = *macAddr;
262  //Send all the packets that are pending for transmission
263  ndpSendQueuedPackets(interface, entry);
264  }
265  }
266  else
267  {
268  //Create a new entry in the Neighbor cache
269  entry = ndpCreateNeighborCacheEntry(interface);
270  }
271 
272  //Neighbor cache entry successfully created?
273  if(entry != NULL)
274  {
275  //Record the IPv6 address and the corresponding MAC address
276  entry->ipAddr = *ipAddr;
277  entry->macAddr = *macAddr;
278 
279  //Unused parameters
280  entry->isRouter = FALSE;
281  entry->timeout = 0;
282  entry->retransmitCount = 0;
283  entry->queueSize = 0;
284 
285  //Update entry state
287 
288  //Successful processing
289  error = NO_ERROR;
290  }
291  else
292  {
293  //Failed to create Neighbor cache entry
294  error = ERROR_OUT_OF_RESOURCES;
295  }
296 
297  //Release exclusive access
299 
300  //Return status code
301  return error;
302 }
303 
304 
305 /**
306  * @brief Remove a static entry from the Neighbor cache
307  * @param[in] interface Underlying network interface
308  * @param[in] ipAddr IPv6 address
309  * @return Error code
310  **/
311 
313 {
314  error_t error;
315  NdpNeighborCacheEntry *entry;
316 
317  //Check parameters
318  if(interface == NULL || ipAddr == NULL)
320 
321  //Get exclusive access
323 
324  //Search the Neighbor cache for the specified IPv6 address
325  entry = ndpFindNeighborCacheEntry(interface, ipAddr);
326 
327  //Check whether a matching entry has been found
328  if(entry != NULL && entry->state == NDP_STATE_PERMANENT)
329  {
330  //Delete Neighbor cache entry
332  //Successful processing
333  error = NO_ERROR;
334  }
335  else
336  {
337  //No matching entry in Neighbor cache
338  error = ERROR_NOT_FOUND;
339  }
340 
341  //Release exclusive access
343 
344  //Return status code
345  return error;
346 }
347 
348 
349 /**
350  * @brief Address resolution using Neighbor Discovery protocol
351  * @param[in] interface Underlying network interface
352  * @param[in] ipAddr IPv6 address
353  * @param[in] macAddr Physical address matching the specified IPv6 address
354  * @return Error code
355  **/
356 
358  MacAddr *macAddr)
359 {
360  error_t error;
361  NdpNeighborCacheEntry *entry;
362 
363  //Search the ndpCacheMutex cache for the specified IPv6 address
364  entry = ndpFindNeighborCacheEntry(interface, ipAddr);
365 
366  //Check whether a matching entry has been found
367  if(entry != NULL)
368  {
369  //Check the state of the Neighbor cache entry
370  if(entry->state == NDP_STATE_INCOMPLETE)
371  {
372  //The address resolution is already in progress
373  error = ERROR_IN_PROGRESS;
374  }
375  else if(entry->state == NDP_STATE_STALE)
376  {
377  //Copy the MAC address associated with the specified IPv6 address
378  *macAddr = entry->macAddr;
379 
380  //Delay before sending the first probe
382  //Switch to the DELAY state
384 
385  //Successful address resolution
386  error = NO_ERROR;
387  }
388  else
389  {
390  //Copy the MAC address associated with the specified IPv6 address
391  *macAddr = entry->macAddr;
392 
393  //Successful address resolution
394  error = NO_ERROR;
395  }
396  }
397  else
398  {
399  //Check whether Neighbor Discovery protocol is enabled
400  if(interface->ndpContext.enable)
401  {
402  //If no entry exists, then create a new one
403  entry = ndpCreateNeighborCacheEntry(interface);
404 
405  //Neighbor cache entry successfully created?
406  if(entry != NULL)
407  {
408  //Record the IPv6 address whose MAC address is unknown
409  entry->ipAddr = *ipAddr;
410 
411  //Reset retransmission counter
412  entry->retransmitCount = 0;
413  //No packet are pending in the transmit queue
414  entry->queueSize = 0;
415 
416  //Send a multicast Neighbor Solicitation message
417  ndpSendNeighborSol(interface, ipAddr, TRUE);
418 
419  //Set timeout value
420  entry->timeout = interface->ndpContext.retransTimer;
421  //Enter INCOMPLETE state
423 
424  //The address resolution is in progress
425  error = ERROR_IN_PROGRESS;
426  }
427  else
428  {
429  //Failed to create Neighbor cache entry
430  error = ERROR_OUT_OF_RESOURCES;
431  }
432  }
433  else
434  {
435  //Neighbor Discovery protocol is disabled
436  error = ERROR_INVALID_ADDRESS;
437  }
438  }
439 
440  //Return status code
441  return error;
442 }
443 
444 
445 /**
446  * @brief Enqueue an IPv6 packet waiting for address resolution
447  * @param[in] srcInterface Interface from which the packet has been received
448  * @param[in] destInterface Interface on which the packet should be sent
449  * @param[in] ipAddr IPv6 address of the destination host
450  * @param[in] buffer Multi-part buffer containing the packet to be enqueued
451  * @param[in] offset Offset to the first byte of the packet
452  * @param[in] ancillary Additional options passed to the stack along with
453  * the packet
454  * @return Error code
455  **/
456 
458  NetInterface *destInterface, const Ipv6Addr *ipAddr, NetBuffer *buffer,
459  size_t offset, NetTxAncillary *ancillary)
460 {
461  error_t error;
462  uint_t i;
463  size_t length;
464  NdpNeighborCacheEntry *entry;
465 
466  //Retrieve the length of the multi-part buffer
467  length = netBufferGetLength(buffer);
468 
469  //Search the Neighbor cache for the specified IPv6 address
470  entry = ndpFindNeighborCacheEntry(destInterface, ipAddr);
471 
472  //Check whether a matching entry exists
473  if(entry != NULL)
474  {
475  //Check the state of the Neighbor cache entry
476  if(entry->state == NDP_STATE_INCOMPLETE)
477  {
478  //Check whether the packet queue is full
479  if(entry->queueSize >= NDP_MAX_PENDING_PACKETS)
480  {
481  //When the queue overflows, the new arrival should replace the
482  //oldest entry
483  netBufferFree(entry->queue[0].buffer);
484 
485  //Make room for the new packet
486  for(i = 1; i < NDP_MAX_PENDING_PACKETS; i++)
487  {
488  entry->queue[i - 1] = entry->queue[i];
489  }
490 
491  //Adjust the number of pending packets
492  entry->queueSize--;
493  }
494 
495  //Index of the entry to be filled in
496  i = entry->queueSize;
497  //Allocate a memory buffer to store the packet
498  entry->queue[i].buffer = netBufferAlloc(length);
499 
500  //Successful memory allocation?
501  if(entry->queue[i].buffer != NULL)
502  {
503  //If the IPv6 packet has been forwarded, record the network
504  //interface from which the packet has been received
505  entry->queue[i].srcInterface = srcInterface;
506 
507  //Copy the contents of the IPv6 packet
508  netBufferCopy(entry->queue[i].buffer, 0, buffer, 0, length);
509  //Offset to the first byte of the IPv6 header
510  entry->queue[i].offset = offset;
511  //Additional options passed to the stack along with the packet
512  entry->queue[i].ancillary = *ancillary;
513 
514  //Increment the number of queued packets
515  entry->queueSize++;
516  //The packet was successfully enqueued
517  error = NO_ERROR;
518  }
519  else
520  {
521  //Failed to allocate memory
522  error = ERROR_OUT_OF_MEMORY;
523  }
524  }
525  else
526  {
527  //The address is already resolved
528  error = ERROR_UNEXPECTED_STATE;
529  }
530  }
531  else
532  {
533  //No matching entry in Neighbor Cache
534  error = ERROR_NOT_FOUND;
535  }
536 
537  //Return status code
538  return error;
539 }
540 
541 
542 /**
543  * @brief NDP timer handler
544  * @param[in] interface Underlying network interface
545  **/
546 
547 void ndpTick(NetInterface *interface)
548 {
549  systime_t time;
550  NdpContext *context;
551 
552  //Point to the NDP context
553  context = &interface->ndpContext;
554 
555  //Get current time
556  time = osGetSystemTime();
557 
558  //When an interface becomes enabled, a host may send some Router
559  //Solicitation messages to obtain Router Advertisements quickly
560  if(interface->linkState && !interface->ipv6Context.isRouter)
561  {
562  //Make sure that a valid link-local address has been assigned to the
563  //interface
565  {
566  //The host should transmit up to MAX_RTR_SOLICITATIONS Router
567  //Solicitation messages
568  if(context->rtrSolicitationCount == 0)
569  {
570  //Set time stamp
571  context->timestamp = time;
572 
573  //Check whether the host has already performed Duplicate Address
574  //Detection for the link-local address
575  if(context->dupAddrDetectTransmits > 0)
576  {
577  //If a host has already performed a random delay since the
578  //interface became enabled, there is no need to delay again
579  //before sending the first Router Solicitation message
580  context->timeout = 0;
581  }
582  else
583  {
584  //Before a host sends an initial solicitation, it should delay the
585  //transmission for a random amount of time in order to alleviate
586  //congestion when many hosts start up on a link at the same time
588  context->maxRtrSolicitationDelay);
589  }
590 
591  //Prepare to send the first Router Solicitation message
592  context->rtrSolicitationCount = 1;
593  }
594  else if(context->rtrSolicitationCount <= context->maxRtrSolicitations)
595  {
596  //Once the host sends a Router Solicitation, and receives a valid
597  //Router Advertisement with a non-zero Router Lifetime, the host must
598  //desist from sending additional solicitations on that interface
599  if(!context->rtrAdvReceived)
600  {
601  //Check current time
602  if(timeCompare(time, context->timestamp + context->timeout) >= 0)
603  {
604  //Send Router Solicitation message
605  ndpSendRouterSol(interface);
606 
607  //Save the time at which the message was sent
608  context->timestamp = time;
609  //Set timeout value
610  context->timeout = context->rtrSolicitationInterval;
611  //Increment retransmission counter
612  context->rtrSolicitationCount++;
613  }
614  }
615  }
616  }
617  }
618 
619  //Periodically update the Neighbor Cache
620  ndpUpdateNeighborCache(interface);
621 
622  //Manage the lifetime of IPv6 addresses
623  ndpUpdateAddrList(interface);
624 
625  //Periodically update the Prefix List
626  ndpUpdatePrefixList(interface);
627 
628  //Periodically update the Default Router List
629  ndpUpdateDefaultRouterList(interface);
630 }
631 
632 
633 /**
634  * @brief Callback function for link change event
635  * @param[in] interface Underlying network interface
636  **/
637 
639 {
640  NdpContext *context;
641 
642  //Point to the NDP context
643  context = &interface->ndpContext;
644 
645  //Restore default parameters
647  context->retransTimer = NDP_RETRANS_TIMER;
653 
654  //Reset retransmission counter for RS messages
655  context->rtrSolicitationCount = 0;
656  //Valid RA message not yet received
657  context->rtrAdvReceived = FALSE;
658 
659  //Flush the Neighbor Cache
660  ndpFlushNeighborCache(interface);
661  //Flush the Destination Cache
662  ndpFlushDestCache(interface);
663 }
664 
665 
666 /**
667  * @brief Router Advertisement message processing
668  * @param[in] interface Underlying network interface
669  * @param[in] pseudoHeader IPv6 pseudo header
670  * @param[in] buffer Multi-part buffer containing the Router Advertisement message
671  * @param[in] offset Offset to the first byte of the message
672  * @param[in] ancillary Additional options passed to the stack along with
673  * the packet
674  **/
675 
677  const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer,
678  size_t offset, const NetRxAncillary *ancillary)
679 {
680  error_t error;
681  uint32_t n;
682  size_t length;
684  NdpMtuOption *mtuOption;
685  NdpPrefixInfoOption *prefixInfoOption;
686 #if (ETH_SUPPORT == ENABLED)
687  NdpLinkLayerAddrOption *linkLayerAddrOption;
688  NdpNeighborCacheEntry *entry;
689 #endif
690 
691  //Retrieve the length of the message
692  length = netBufferGetLength(buffer) - offset;
693 
694  //Check the length of the Router Advertisement message
695  if(length < sizeof(NdpRouterAdvMessage))
696  return;
697 
698  //Point to the beginning of the message
699  message = netBufferAt(buffer, offset, length);
700  //Sanity check
701  if(message == NULL)
702  return;
703 
704  //Debug message
705  TRACE_INFO("Router Advertisement message received (%" PRIuSIZE " bytes)...\r\n", length);
706  //Dump message contents for debugging purpose
708 
709  //Routers must use their link-local address as the source for the
710  //Router Advertisement so that hosts can uniquely identify routers
711  if(!ipv6IsLinkLocalUnicastAddr(&pseudoHeader->srcAddr))
712  return;
713 
714  //The IPv6 Hop Limit field must have a value of 255 to ensure that the
715  //packet has not been forwarded by a router
716  if(ancillary->ttl != NDP_HOP_LIMIT)
717  return;
718 
719  //ICMPv6 Code must be 0. An advertisement that passes the validity
720  //checks is called a valid advertisement
721  if(message->code)
722  return;
723 
724  //Calculate the length of the Options field
725  length -= sizeof(NdpRouterAdvMessage);
726 
727  //Parse Options field
728  error = ndpCheckOptions(message->options, length);
729  //All included options must have a length that is greater than zero
730  if(error)
731  return;
732 
733  //Check the Router Lifetime value
734  if(ntohs(message->routerLifetime) != 0)
735  {
736  //Add a new entry in the Default Router List
737  ipv6AddDefaultRouter(interface, &pseudoHeader->srcAddr,
738  ntohs(message->routerLifetime), message->prf);
739 
740  //The host should send at least one solicitation in the case where
741  //an advertisement is received prior to having sent a solicitation
742  if(interface->ndpContext.rtrSolicitationCount > 1)
743  {
744  //Once the host sends a Router Solicitation, and receives a valid
745  //Router Advertisement with a non-zero Router Lifetime, the host must
746  //desist from sending additional solicitations on that interface
747  interface->ndpContext.rtrAdvReceived = TRUE;
748  }
749  }
750  else
751  {
752  //Immediately time-out the entry
753  ipv6RemoveDefaultRouter(interface, &pseudoHeader->srcAddr);
754  }
755 
756  //6LoWPAN interface?
757  if(interface->nicDriver != NULL &&
758  interface->nicDriver->type == NIC_TYPE_6LOWPAN)
759  {
760  //In all cases, the Router Solicitation retransmissions are terminated
761  //when a Router Advertisement is received (refer to RFC 6675 5.3)
762  interface->ndpContext.rtrAdvReceived = TRUE;
763  }
764 
765  //A Router Advertisement field (Cur Hop Limit, Reachable Time, and
766  //Retrans Timer) may contain a value denoting that it is unspecified.
767  //In such cases, the parameter should be ignored and the host should
768  //continue using whatever value it is already using
769  if(message->curHopLimit != 0)
770  {
771  //Get the default value that should be placed in the Hop Count
772  //field of the IP header for outgoing IP packets
773  interface->ipv6Context.curHopLimit = message->curHopLimit;
774  }
775 
776  //A value of zero means unspecified
777  if(message->reachableTime != 0)
778  {
779  //The Reachable Time field holds the time, in milliseconds, that
780  //a node assumes a neighbor is reachable after having received a
781  //reachability confirmation
782  interface->ndpContext.reachableTime = ntohl(message->reachableTime);
783  }
784 
785  //A value of zero means unspecified
786  if(message->retransTimer != 0)
787  {
788  //The Retrans Timer field holds the time, in milliseconds, between
789  //retransmitted Neighbor Solicitation messages
790  interface->ndpContext.retransTimer = ntohl(message->retransTimer);
791  }
792 
793 #if (ETH_SUPPORT == ENABLED)
794  //Search for the Source Link-Layer Address option
795  linkLayerAddrOption = ndpGetOption(message->options, length,
797 
798  //Source Link-Layer Address option found?
799  if(linkLayerAddrOption != NULL && linkLayerAddrOption->length == 1)
800  {
801  //Debug message
802  TRACE_DEBUG(" Source Link-Layer Address = %s\r\n",
803  macAddrToString(&linkLayerAddrOption->linkLayerAddr, NULL));
804  }
805  else
806  {
807  //No valid Source Link-Layer Address option...
808  linkLayerAddrOption = NULL;
809  }
810 
811  //Search the Neighbor cache for the router
812  entry = ndpFindNeighborCacheEntry(interface, &pseudoHeader->srcAddr);
813 
814  //No matching entry found?
815  if(entry == NULL)
816  {
817  //If the advertisement contains a Source Link-Layer Address option,
818  //the link-layer address should be recorded in the Neighbor cache
819  if(linkLayerAddrOption)
820  {
821  //Check whether Neighbor Discovery protocol is enabled
822  if(interface->ndpContext.enable)
823  {
824  //Create a new entry for the router
825  entry = ndpCreateNeighborCacheEntry(interface);
826 
827  //Neighbor cache entry successfully created?
828  if(entry != NULL)
829  {
830  //Record the IPv6 address and the corresponding MAC address
831  entry->ipAddr = pseudoHeader->srcAddr;
832  entry->macAddr = linkLayerAddrOption->linkLayerAddr;
833 
834  //The IsRouter flag must be set to TRUE
835  entry->isRouter = TRUE;
836 
837  //The reachability state must be set to STALE
839  }
840  }
841  }
842  }
843  else
844  {
845  //The sender of a Router Advertisement is implicitly assumed to be a
846  //router
847  entry->isRouter = TRUE;
848 
849  //Check if the advertisement contains a Source Link-Layer Address option
850  if(linkLayerAddrOption)
851  {
852  //Check the state of the Neighbor cache entry
853  if(entry->state == NDP_STATE_PERMANENT)
854  {
855  //Static Neighbor cache entries are never updated
856  }
857  else if(entry->state == NDP_STATE_INCOMPLETE)
858  {
859  //Record link-layer address
860  entry->macAddr = linkLayerAddrOption->linkLayerAddr;
861 
862  //Send all the packets that are pending for transmission
863  n = ndpSendQueuedPackets(interface, entry);
864 
865  //Check whether any packets have been sent
866  if(n > 0)
867  {
868  //Start delay timer
870  //Switch to the DELAY state
872  }
873  else
874  {
875  //Enter the STALE state
877  }
878  }
879  else
880  {
881  //Different link-layer address than cached?
882  if(!macCompAddr(&entry->macAddr, &linkLayerAddrOption->linkLayerAddr))
883  {
884  //Update link-layer address
885  entry->macAddr = linkLayerAddrOption->linkLayerAddr;
886 
887  //The reachability state must be set to STALE
889  }
890  }
891  }
892  }
893 #endif
894 
895  //Search for the MTU option
896  mtuOption = ndpGetOption(message->options, length, NDP_OPT_MTU);
897 
898  //MTU option found?
899  if(mtuOption != NULL && mtuOption->length == 1)
900  {
901  NetInterface *physicalInterface;
902 
903  //Point to the physical interface
904  physicalInterface = nicGetPhysicalInterface(interface);
905 
906  //This option specifies the recommended MTU for the link
907  n = ntohl(mtuOption->mtu);
908 
909  //The host should copy the option's value so long as the value is greater
910  //than or equal to the minimum IPv6 MTU and does not exceed the maximum
911  //MTU of the interface
912  if(n >= IPV6_DEFAULT_MTU && n <= physicalInterface->nicDriver->mtu)
913  {
914  //Save the MTU value
915  interface->ipv6Context.linkMtu = n;
916  }
917  }
918 
919  //Point to the beginning of the Options field
920  n = 0;
921 
922  //Parse Options field
923  while(1)
924  {
925  //Search the Options field for any Prefix Information options
926  prefixInfoOption = ndpGetOption(message->options + n, length - n,
928 
929  //No more option of the specified type?
930  if(prefixInfoOption == NULL)
931  break;
932 
933  //Hosts use the advertised on-link prefixes to build and maintain a list
934  //that is used in deciding when a packet's destination is on-link or
935  //beyond a router
936  ndpParsePrefixInfoOption(interface, prefixInfoOption);
937 
938  //Retrieve the offset to the current position
939  n = (uint8_t *) prefixInfoOption - message->options;
940  //Jump to the next option
941  n += prefixInfoOption->length * 8;
942  }
943 
944 #if (SLAAC_SUPPORT == ENABLED)
945  //Stateless Address Autoconfiguration is currently used?
946  if(interface->slaacContext != NULL)
947  {
948  //Process the valid advertisement
949  slaacParseRouterAdv(interface->slaacContext, message,
950  length + sizeof(NdpRouterAdvMessage));
951  }
952 #endif
953 }
954 
955 
956 /**
957  * @brief Neighbor Solicitation message processing
958  * @param[in] interface Underlying network interface
959  * @param[in] pseudoHeader IPv6 pseudo header
960  * @param[in] buffer Multi-part buffer containing the Neighbor Solicitation message
961  * @param[in] offset Offset to the first byte of the message
962  * @param[in] ancillary Additional options passed to the stack along with
963  * the packet
964  **/
965 
967  const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer,
968  size_t offset, const NetRxAncillary *ancillary)
969 {
970 #if (ETH_SUPPORT == ENABLED)
971  error_t error;
972  uint_t i;
973  uint_t n;
974  size_t length;
975  bool_t validTarget;
977  NdpLinkLayerAddrOption *option;
978  NdpNeighborCacheEntry *neighborCacheEntry;
979  Ipv6AddrEntry *addrEntry;
980 
981  //Retrieve the length of the message
982  length = netBufferGetLength(buffer) - offset;
983 
984  //Check the length of the Neighbor Solicitation message
985  if(length < sizeof(NdpNeighborSolMessage))
986  return;
987 
988  //Point to the beginning of the message
989  message = netBufferAt(buffer, offset, length);
990  //Sanity check
991  if(message == NULL)
992  return;
993 
994  //Debug message
995  TRACE_INFO("Neighbor Solicitation message received (%" PRIuSIZE " bytes)...\r\n", length);
996  //Dump message contents for debugging purpose
998 
999  //The IPv6 Hop Limit field must have a value of 255 to ensure that the
1000  //packet has not been forwarded by a router
1001  if(ancillary->ttl != NDP_HOP_LIMIT)
1002  return;
1003 
1004  //ICMPv6 Code must be 0
1005  if(message->code)
1006  return;
1007 
1008  //If the IP source address is the unspecified address, the IP destination
1009  //address must be a solicited-node multicast address
1010  if(ipv6CompAddr(&pseudoHeader->srcAddr, &IPV6_UNSPECIFIED_ADDR) &&
1011  !ipv6IsSolicitedNodeAddr(&pseudoHeader->destAddr))
1012  {
1013  //Debug message
1014  TRACE_WARNING("Destination address must be a solicited-node address!\r\n");
1015  //Exit immediately
1016  return;
1017  }
1018 
1019  //Calculate the length of the Options field
1020  length -= sizeof(NdpNeighborSolMessage);
1021 
1022  //Parse Options field
1023  error = ndpCheckOptions(message->options, length);
1024  //All included options must have a length that is greater than zero
1025  if(error)
1026  return;
1027 
1028  //Search for the Source Link-Layer Address option
1029  option = ndpGetOption(message->options, length,
1031 
1032  //The target address must a valid unicast or anycast address assigned to
1033  //the interface or a tentative address on which DAD is being performed
1034  validTarget = FALSE;
1035 
1036  //Loop through the IPv6 addresses assigned to the interface
1037  for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
1038  {
1039  //Point to the current entry
1040  addrEntry = &interface->ipv6Context.addrList[i];
1041 
1042  //Compare target address
1043  if(ipv6CompAddr(&addrEntry->addr, &message->targetAddr))
1044  {
1045  //Check address state
1046  if(addrEntry->state == IPV6_ADDR_STATE_TENTATIVE)
1047  {
1048  //If the source address of the Neighbor Solicitation is the
1049  //unspecified address, the solicitation is from a node performing
1050  //Duplicate Address Detection
1051  if(ipv6CompAddr(&pseudoHeader->srcAddr, &IPV6_UNSPECIFIED_ADDR))
1052  {
1053  //The source link-layer address must not be included when the
1054  //source IP address is the unspecified address
1055  if(option == NULL)
1056  {
1057  //Debug message
1058  TRACE_WARNING("The tentative address %s is a duplicate!\r\n",
1059  ipv6AddrToString(&addrEntry->addr, NULL));
1060 
1061  //The tentative address is a duplicate and should not be used
1062  addrEntry->duplicate = TRUE;
1063  }
1064  }
1065 
1066  //In all cases, a node must not respond to a Neighbor Solicitation
1067  //for a tentative address
1068  return;
1069  }
1070  else if(addrEntry->state != IPV6_ADDR_STATE_INVALID)
1071  {
1072  //The target address is a valid address assigned to the interface
1073  validTarget = TRUE;
1074  //We are done
1075  break;
1076  }
1077  }
1078  }
1079 
1080  //Invalid target address?
1081  if(!validTarget)
1082  {
1083  //The Neighbor Solicitation must be discarded if the target address
1084  //is not a valid anycast address assigned to the interface
1085  if(!ipv6IsAnycastAddr(interface, &message->targetAddr))
1086  {
1087  //Debug message
1088  TRACE_WARNING("Wrong target address!\r\n");
1089  //Exit immediately
1090  return;
1091  }
1092  }
1093 
1094  //Source Link-Layer Address option found?
1095  if(option != NULL && option->length == 1)
1096  {
1097  //Debug message
1098  TRACE_DEBUG(" Source Link-Layer Address = %s\r\n",
1099  macAddrToString(&option->linkLayerAddr, NULL));
1100 
1101  //The Source Link-Layer Address option must not be included when the
1102  //source IP address is the unspecified address
1103  if(ipv6CompAddr(&pseudoHeader->srcAddr, &IPV6_UNSPECIFIED_ADDR))
1104  return;
1105 
1106  //Search the Neighbor Cache for the source address of the solicitation
1107  neighborCacheEntry = ndpFindNeighborCacheEntry(interface,
1108  &pseudoHeader->srcAddr);
1109 
1110  //No matching entry found?
1111  if(neighborCacheEntry == NULL)
1112  {
1113  //Check whether Neighbor Discovery protocol is enabled
1114  if(interface->ndpContext.enable)
1115  {
1116  //Create a new entry
1117  neighborCacheEntry = ndpCreateNeighborCacheEntry(interface);
1118 
1119  //Neighbor cache entry successfully created?
1120  if(neighborCacheEntry != NULL)
1121  {
1122  //Record the IPv6 and the corresponding MAC address
1123  neighborCacheEntry->ipAddr = pseudoHeader->srcAddr;
1124  neighborCacheEntry->macAddr = option->linkLayerAddr;
1125 
1126  //Enter the STALE state
1127  ndpChangeState(neighborCacheEntry, NDP_STATE_STALE);
1128  }
1129  }
1130  }
1131  else
1132  {
1133  //Check the state of the Neighbor cache entry
1134  if(neighborCacheEntry->state == NDP_STATE_PERMANENT)
1135  {
1136  //Static Neighbor cache entries are never updated
1137  }
1138  else if(neighborCacheEntry->state == NDP_STATE_INCOMPLETE)
1139  {
1140  //Record link-layer address
1141  neighborCacheEntry->macAddr = option->linkLayerAddr;
1142 
1143  //Send all the packets that are pending for transmission
1144  n = ndpSendQueuedPackets(interface, neighborCacheEntry);
1145 
1146  //Check whether any packets have been sent
1147  if(n > 0)
1148  {
1149  //Start delay timer
1150  neighborCacheEntry->timeout = NDP_DELAY_FIRST_PROBE_TIME;
1151  //Switch to the DELAY state
1152  ndpChangeState(neighborCacheEntry, NDP_STATE_DELAY);
1153  }
1154  else
1155  {
1156  //Enter the STALE state
1157  ndpChangeState(neighborCacheEntry, NDP_STATE_STALE);
1158  }
1159  }
1160  else
1161  {
1162  //Different link-layer address than cached?
1163  if(!macCompAddr(&neighborCacheEntry->macAddr, &option->linkLayerAddr))
1164  {
1165  //Update link-layer address
1166  neighborCacheEntry->macAddr = option->linkLayerAddr;
1167 
1168  //Enter the STALE state
1169  ndpChangeState(neighborCacheEntry, NDP_STATE_STALE);
1170  }
1171  }
1172  }
1173  }
1174  //Source Link-Layer Address option not found?
1175  else
1176  {
1177  //The Source Link-Layer Address option must not be included when the
1178  //source IP address is the unspecified address. Otherwise, this option
1179  //must be included in multicast solicitations
1180  if(!ipv6CompAddr(&pseudoHeader->srcAddr, &IPV6_UNSPECIFIED_ADDR) &&
1181  ipv6IsMulticastAddr(&pseudoHeader->destAddr))
1182  {
1183  //Debug message
1184  TRACE_WARNING("The Source Link-Layer Address must be included!\r\n");
1185  //Exit immediately
1186  return;
1187  }
1188  }
1189 
1190  //Check whether a Neighbor Advertisement should be sent in response
1191  if(interface->ndpContext.enable)
1192  {
1193  //After any updates to the Neighbor cache, the node sends a Neighbor
1194  //Advertisement response as described in RFC 4861 7.2.4
1195  ndpSendNeighborAdv(interface, &message->targetAddr,
1196  &pseudoHeader->srcAddr);
1197  }
1198 #endif
1199 }
1200 
1201 
1202 /**
1203  * @brief Neighbor Advertisement message processing
1204  * @param[in] interface Underlying network interface
1205  * @param[in] pseudoHeader IPv6 pseudo header
1206  * @param[in] buffer Multi-part buffer containing the Neighbor Advertisement message
1207  * @param[in] offset Offset to the first byte of the message
1208  * @param[in] ancillary Additional options passed to the stack along with
1209  * the packet
1210  **/
1211 
1213  const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer,
1214  size_t offset, const NetRxAncillary *ancillary)
1215 {
1216 #if (ETH_SUPPORT == ENABLED)
1217  error_t error;
1218  uint_t i;
1219  uint_t n;
1220  size_t length;
1221  bool_t differentLinkLayerAddr;
1223  NdpLinkLayerAddrOption *option;
1224  NdpNeighborCacheEntry *neighborCacheEntry;
1225  Ipv6AddrEntry *addrEntry;
1226 
1227  //Retrieve the length of the message
1228  length = netBufferGetLength(buffer) - offset;
1229 
1230  //Check the length of the Neighbor Advertisement message
1231  if(length < sizeof(NdpNeighborAdvMessage))
1232  return;
1233 
1234  //Point to the beginning of the message
1235  message = netBufferAt(buffer, offset, length);
1236  //Sanity check
1237  if(message == NULL)
1238  return;
1239 
1240  //Debug message
1241  TRACE_INFO("Neighbor Advertisement message received (%" PRIuSIZE " bytes)...\r\n", length);
1242  //Dump message contents for debugging purpose
1244 
1245  //The IPv6 Hop Limit field must have a value of 255 to ensure that the
1246  //packet has not been forwarded by a router
1247  if(ancillary->ttl != NDP_HOP_LIMIT)
1248  return;
1249 
1250  //ICMPv6 Code must be 0
1251  if(message->code)
1252  return;
1253 
1254  //The target address must not be a multicast address
1255  if(ipv6IsMulticastAddr(&message->targetAddr))
1256  {
1257  //Debug message
1258  TRACE_WARNING("Target address must not be a multicast address!\r\n");
1259  //Exit immediately
1260  return;
1261  }
1262 
1263  //If the destination address is a multicast address
1264  //then the Solicited flag must be zero
1265  if(ipv6IsMulticastAddr(&pseudoHeader->destAddr) && message->s)
1266  {
1267  //Debug message
1268  TRACE_WARNING("Solicited flag must be zero!\r\n");
1269  //Exit immediately
1270  return;
1271  }
1272 
1273  //Calculate the length of the Options field
1274  length -= sizeof(NdpNeighborAdvMessage);
1275 
1276  //Parse Options field
1277  error = ndpCheckOptions(message->options, length);
1278  //All included options must have a length that is greater than zero
1279  if(error)
1280  return;
1281 
1282  //Duplicate address detection
1283  for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
1284  {
1285  //Point to the current entry
1286  addrEntry = &interface->ipv6Context.addrList[i];
1287 
1288  //Valid entry?
1289  if(addrEntry->state != IPV6_ADDR_STATE_INVALID)
1290  {
1291  //Check whether the target address is tentative or matches a unicast
1292  //address assigned to the interface
1293  if(ipv6CompAddr(&addrEntry->addr, &message->targetAddr))
1294  {
1295  //Debug message
1296  TRACE_WARNING("The address %s is a duplicate!\r\n",
1297  ipv6AddrToString(&addrEntry->addr, NULL));
1298 
1299  //The address is a duplicate and should not be used
1300  addrEntry->duplicate = TRUE;
1301  //Exit immediately
1302  return;
1303  }
1304  }
1305  }
1306 
1307  //Search the Neighbor cache for the specified target address
1308  neighborCacheEntry = ndpFindNeighborCacheEntry(interface, &message->targetAddr);
1309 
1310  //If no entry exists, the advertisement should be silently discarded
1311  if(neighborCacheEntry != NULL)
1312  {
1313  //This flag tells whether the supplied link-layer
1314  //address differs from that in the cache
1315  differentLinkLayerAddr = FALSE;
1316 
1317  //Search for the Target Link-Layer Address option
1318  option = ndpGetOption(message->options, length,
1320 
1321  //Target Link-Layer Address option found?
1322  if(option != NULL && option->length == 1)
1323  {
1324  //Debug message
1325  TRACE_DEBUG(" Target Link-Layer Address = %s\r\n",
1326  macAddrToString(&option->linkLayerAddr, NULL));
1327 
1328  //Different link-layer address than cached?
1329  if(!macCompAddr(&neighborCacheEntry->macAddr, &option->linkLayerAddr))
1330  {
1331  differentLinkLayerAddr = TRUE;
1332  }
1333  }
1334 
1335  //Check the state of the Neighbor cache entry
1336  if(neighborCacheEntry->state == NDP_STATE_PERMANENT)
1337  {
1338  //Static Neighbor cache entries are never updated
1339  }
1340  else if(neighborCacheEntry->state == NDP_STATE_INCOMPLETE)
1341  {
1342  //If no Target Link-Layer Address option is included, the receiving
1343  //node should silently discard the received advertisement
1344  if(option != NULL && option->length == 1)
1345  {
1346  //Record the link-layer address
1347  neighborCacheEntry->macAddr = option->linkLayerAddr;
1348 
1349  //Send all the packets that are pending for transmission
1350  n = ndpSendQueuedPackets(interface, neighborCacheEntry);
1351 
1352  //Solicited flag is set?
1353  if(message->s)
1354  {
1355  //Computing the random ReachableTime value
1356  neighborCacheEntry->timeout = interface->ndpContext.reachableTime;
1357  //Switch to the REACHABLE state
1358  ndpChangeState(neighborCacheEntry, NDP_STATE_REACHABLE);
1359  }
1360  else
1361  {
1362  //Check whether any packets have been sent
1363  if(n > 0)
1364  {
1365  //Start delay timer
1366  neighborCacheEntry->timeout = NDP_DELAY_FIRST_PROBE_TIME;
1367  //Switch to the DELAY state
1368  ndpChangeState(neighborCacheEntry, NDP_STATE_DELAY);
1369  }
1370  else
1371  {
1372  //Enter the STALE state
1373  ndpChangeState(neighborCacheEntry, NDP_STATE_STALE);
1374  }
1375  }
1376  }
1377  }
1378  else
1379  {
1380  //Check whether the Override flag is clear and the supplied link-layer
1381  //address differs from that in the cache
1382  if(!message->o && differentLinkLayerAddr)
1383  {
1384  //REACHABLE state?
1385  if(neighborCacheEntry->state == NDP_STATE_REACHABLE)
1386  {
1387  //Enter the STALE state
1388  ndpChangeState(neighborCacheEntry, NDP_STATE_STALE);
1389  }
1390  }
1391  else
1392  {
1393  //Solicited flag is set?
1394  if(message->s)
1395  {
1396  //Different link-layer address than cached?
1397  if(differentLinkLayerAddr)
1398  {
1399  //The link-layer address must be inserted in the cache
1400  neighborCacheEntry->macAddr = option->linkLayerAddr;
1401  }
1402 
1403  //Computing the random ReachableTime value
1404  neighborCacheEntry->timeout = interface->ndpContext.reachableTime;
1405  //Switch to the REACHABLE state
1406  ndpChangeState(neighborCacheEntry, NDP_STATE_REACHABLE);
1407  }
1408  else
1409  {
1410  //Different link-layer address than cached?
1411  if(differentLinkLayerAddr)
1412  {
1413  //The link-layer address must be inserted in the cache
1414  neighborCacheEntry->macAddr = option->linkLayerAddr;
1415 
1416  //The state must be set to STALE
1417  ndpChangeState(neighborCacheEntry, NDP_STATE_STALE);
1418  }
1419  }
1420  }
1421  }
1422 
1423  //The IsRouter flag in the cache entry must be set based on the Router
1424  //flag in the received advertisement
1425  if(message->r)
1426  {
1427  //The neighbor is a router
1428  neighborCacheEntry->isRouter = TRUE;
1429  }
1430  else
1431  {
1432  //Check whether the IsRouter flag changes from TRUE to FALSE as a
1433  //result of this update
1434  if(neighborCacheEntry->isRouter)
1435  {
1436  //The node must remove that router from the Default Router list
1437  //and update the Destination cache entries for all destinations
1438  //using that neighbor as a router
1439  ipv6RemoveDefaultRouter(interface, &neighborCacheEntry->ipAddr);
1440  }
1441 
1442  //The neighbor is a host
1443  neighborCacheEntry->isRouter = FALSE;
1444  }
1445  }
1446 #endif
1447 }
1448 
1449 
1450 /**
1451  * @brief Redirect message processing
1452  * @param[in] interface Underlying network interface
1453  * @param[in] pseudoHeader IPv6 pseudo header
1454  * @param[in] buffer Multi-part buffer containing the Redirect message
1455  * @param[in] offset Offset to the first byte of the message
1456  * @param[in] ancillary Additional options passed to the stack along with
1457  * the packet
1458  **/
1459 
1461  const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer,
1462  size_t offset, const NetRxAncillary *ancillary)
1463 {
1464 #if (ETH_SUPPORT == ENABLED)
1465  error_t error;
1466  uint_t n;
1467  size_t length;
1469  NdpLinkLayerAddrOption *option;
1470  NdpNeighborCacheEntry *neighborCacheEntry;
1471  NdpDestCacheEntry *destCacheEntry;
1472 
1473  //Retrieve the length of the message
1474  length = netBufferGetLength(buffer) - offset;
1475 
1476  //Check the length of the Redirect message
1477  if(length < sizeof(NdpRedirectMessage))
1478  return;
1479 
1480  //Point to the beginning of the message
1481  message = netBufferAt(buffer, offset, length);
1482  //Sanity check
1483  if(message == NULL)
1484  return;
1485 
1486  //Debug message
1487  TRACE_INFO("Redirect message received (%" PRIuSIZE " bytes)...\r\n", length);
1488  //Dump message contents for debugging purpose
1490 
1491  //The IPv6 Hop Limit field must have a value of 255 to ensure that the
1492  //packet has not been forwarded by a router
1493  if(ancillary->ttl != NDP_HOP_LIMIT)
1494  return;
1495 
1496  //ICMPv6 Code must be 0
1497  if(message->code)
1498  return;
1499 
1500  //Routers must use their link-local address as the source for Redirect
1501  //messages so that hosts can uniquely identify routers
1502  if(!ipv6IsLinkLocalUnicastAddr(&pseudoHeader->srcAddr))
1503  return;
1504 
1505  //The IP source address of the Redirect must be the same as the current
1506  //first-hop router for the specified Destination address
1507  if(!ndpIsFirstHopRouter(interface, &message->destAddr, &pseudoHeader->srcAddr))
1508  return;
1509 
1510  //The Destination Address field in the Redirect message must not
1511  //contain a multicast address
1512  if(ipv6IsMulticastAddr(&message->destAddr))
1513  return;
1514 
1515  //The Target Address must be either a link-local address (when redirected
1516  //to a router) or the same as the Destination Address (when redirected to
1517  //the on-link destination)
1518  if(!ipv6IsLinkLocalUnicastAddr(&message->targetAddr) &&
1519  !ipv6CompAddr(&message->targetAddr, &message->destAddr))
1520  {
1521  //Silently discard the received Redirect message
1522  return;
1523  }
1524 
1525  //Calculate the length of the Options field
1526  length -= sizeof(NdpNeighborAdvMessage);
1527 
1528  //Parse Options field
1529  error = ndpCheckOptions(message->options, length);
1530  //All included options must have a length that is greater than zero
1531  if(error)
1532  return;
1533 
1534  //Search the Destination cache for the specified address
1535  destCacheEntry = ndpFindDestCacheEntry(interface, &message->destAddr);
1536 
1537  //Check whether a corresponding Destination cache entry exists
1538  if(destCacheEntry != NULL)
1539  {
1540  //The entry is updated with information learned from Redirect messages
1541  destCacheEntry->nextHop = message->targetAddr;
1542  //Save current time
1543  destCacheEntry->timestamp = osGetSystemTime();
1544  }
1545  else
1546  {
1547  //If no Destination Cache entry exists for the destination, an
1548  //implementation should create such an entry
1549  destCacheEntry = ndpCreateDestCacheEntry(interface);
1550 
1551  //Destination cache entry successfully created?
1552  if(destCacheEntry != NULL)
1553  {
1554  //Destination address
1555  destCacheEntry->destAddr = message->destAddr;
1556  //Address of the next hop
1557  destCacheEntry->nextHop = message->targetAddr;
1558 
1559  //Initially, the PMTU value for a path is assumed to be
1560  //the MTU of the first-hop link
1561  destCacheEntry->pathMtu = interface->ipv6Context.linkMtu;
1562 
1563  //Save current time
1564  destCacheEntry->timestamp = osGetSystemTime();
1565  }
1566  }
1567 
1568  //Search for the Target Link-Layer Address option
1569  option = ndpGetOption(message->options, length,
1571 
1572  //If the Redirect contains a Target Link-Layer Address option, the host
1573  //either creates or updates the Neighbor Cache entry for the target
1574  if(option != NULL && option->length == 1)
1575  {
1576  //Debug message
1577  TRACE_DEBUG(" Target Link-Layer Address = %s\r\n",
1578  macAddrToString(&option->linkLayerAddr, NULL));
1579 
1580  //Search the Neighbor cache for the specified target address
1581  neighborCacheEntry = ndpFindNeighborCacheEntry(interface,
1582  &message->targetAddr);
1583 
1584  //No matching entry found?
1585  if(neighborCacheEntry == NULL)
1586  {
1587  //Check whether Neighbor Discovery protocol is enabled
1588  if(interface->ndpContext.enable)
1589  {
1590  //Create a new entry for the target
1591  neighborCacheEntry = ndpCreateNeighborCacheEntry(interface);
1592 
1593  //Neighbor cache entry successfully created?
1594  if(neighborCacheEntry != NULL)
1595  {
1596  //Record the Target address
1597  neighborCacheEntry->ipAddr = message->targetAddr;
1598  //The cached link-layer address is copied from the option
1599  neighborCacheEntry->macAddr = option->linkLayerAddr;
1600 
1601  //Newly created Neighbor Cache entries should set the IsRouter
1602  //flag to FALSE
1603  neighborCacheEntry->isRouter = FALSE;
1604 
1605  //The reachability state must be set to STALE
1606  ndpChangeState(neighborCacheEntry, NDP_STATE_STALE);
1607  }
1608  }
1609  }
1610  else
1611  {
1612  //If the Target Address is not the same as the Destination Address,
1613  //the host must set IsRouter to TRUE for the target
1614  if(!ipv6CompAddr(&message->targetAddr, &message->destAddr))
1615  {
1616  neighborCacheEntry->isRouter = TRUE;
1617  }
1618 
1619  //Check the state of the Neighbor cache entry
1620  if(neighborCacheEntry->state == NDP_STATE_PERMANENT)
1621  {
1622  //Static Neighbor cache entries are never updated
1623  }
1624  else if(neighborCacheEntry->state == NDP_STATE_INCOMPLETE)
1625  {
1626  //Record link-layer address
1627  neighborCacheEntry->macAddr = option->linkLayerAddr;
1628 
1629  //Send all the packets that are pending for transmission
1630  n = ndpSendQueuedPackets(interface, neighborCacheEntry);
1631 
1632  //Check whether any packets have been sent
1633  if(n > 0)
1634  {
1635  //Start delay timer
1636  neighborCacheEntry->timeout = NDP_DELAY_FIRST_PROBE_TIME;
1637  //Switch to the DELAY state
1638  ndpChangeState(neighborCacheEntry, NDP_STATE_DELAY);
1639  }
1640  else
1641  {
1642  //Enter the STALE state
1643  ndpChangeState(neighborCacheEntry, NDP_STATE_STALE);
1644  }
1645  }
1646  else
1647  {
1648  //Different link-layer address than cached?
1649  if(!macCompAddr(&neighborCacheEntry->macAddr, &option->linkLayerAddr))
1650  {
1651  //Update link-layer address
1652  neighborCacheEntry->macAddr = option->linkLayerAddr;
1653 
1654  //The reachability state must be set to STALE
1655  ndpChangeState(neighborCacheEntry, NDP_STATE_STALE);
1656  }
1657  }
1658  }
1659  }
1660 #endif
1661 }
1662 
1663 
1664 /**
1665  * @brief Send a Router Solicitation message
1666  * @param[in] interface Underlying network interface
1667  * @return Error code
1668  **/
1669 
1671 {
1672  error_t error;
1673  size_t offset;
1674  size_t length;
1675  NetBuffer *buffer;
1677  Ipv6PseudoHeader pseudoHeader;
1678  NetTxAncillary ancillary;
1679 
1680  //The destination address is typically the all-routers multicast address
1681  pseudoHeader.destAddr = IPV6_LINK_LOCAL_ALL_ROUTERS_ADDR;
1682 
1683  //Select the most appropriate source address to be used when sending the
1684  //Router Solicitation message
1685  error = ipv6SelectSourceAddr(&interface, &pseudoHeader.destAddr,
1686  &pseudoHeader.srcAddr);
1687 
1688  //No address assigned to the interface?
1689  if(error)
1690  {
1691  //Use the unspecified address if no address is assigned
1692  //to the sending interface
1693  pseudoHeader.srcAddr = IPV6_UNSPECIFIED_ADDR;
1694  }
1695 
1696  //The only defined option that may appear in a Router Solicitation
1697  //message is the Source Link-Layer Address option
1699 
1700  //Allocate a memory buffer to hold the Router Solicitation message
1701  buffer = ipAllocBuffer(length, &offset);
1702  //Failed to allocate memory?
1703  if(buffer == NULL)
1704  return ERROR_OUT_OF_MEMORY;
1705 
1706  //Point to the beginning of the message
1707  message = netBufferAt(buffer, offset, 0);
1708 
1709  //Format Router Solicitation message
1711  message->code = 0;
1712  message->checksum = 0;
1713  message->reserved = 0;
1714 
1715  //Length of the message, excluding any option
1716  length = sizeof(NdpRouterSolMessage);
1717 
1718  //The Source Link-Layer Address option must not be included
1719  //when the source IPv6 address is the unspecified address
1720  if(!ipv6CompAddr(&pseudoHeader.srcAddr, &IPV6_UNSPECIFIED_ADDR))
1721  {
1722 #if (ETH_SUPPORT == ENABLED)
1723  NetInterface *logicalInterface;
1724 
1725  //Point to the logical interface
1726  logicalInterface = nicGetLogicalInterface(interface);
1727 
1728  //Check whether a MAC address has been assigned to the interface
1729  if(!macCompAddr(&logicalInterface->macAddr, &MAC_UNSPECIFIED_ADDR))
1730  {
1731  //Add Source Link-Layer Address option
1733  &logicalInterface->macAddr, sizeof(MacAddr));
1734  }
1735 #endif
1736  }
1737 
1738  //Adjust the length of the multi-part buffer
1739  netBufferSetLength(buffer, offset + length);
1740 
1741  //Format IPv6 pseudo header
1742  pseudoHeader.length = htonl(length);
1743  pseudoHeader.reserved[0] = 0;
1744  pseudoHeader.reserved[1] = 0;
1745  pseudoHeader.reserved[2] = 0;
1746  pseudoHeader.nextHeader = IPV6_ICMPV6_HEADER;
1747 
1748  //Calculate ICMPv6 header checksum
1749  message->checksum = ipCalcUpperLayerChecksumEx(&pseudoHeader,
1750  sizeof(Ipv6PseudoHeader), buffer, offset, length);
1751 
1752  //Total number of ICMP messages which this entity attempted to send
1753  IP_MIB_INC_COUNTER32(icmpv6Stats.icmpStatsOutMsgs, 1);
1754  //Increment per-message type ICMP counter
1755  IP_MIB_INC_COUNTER32(icmpv6MsgStatsTable.icmpMsgStatsOutPkts[ICMPV6_TYPE_ROUTER_SOL], 1);
1756 
1757  //Debug message
1758  TRACE_INFO("Sending Router Solicitation message (%" PRIuSIZE " bytes)...\r\n", length);
1759  //Dump message contents for debugging purpose
1761 
1762  //Additional options can be passed to the stack along with the packet
1763  ancillary = NET_DEFAULT_TX_ANCILLARY;
1764 
1765  //By setting the Hop Limit to 255, Neighbor Discovery is immune to off-link
1766  //senders that accidentally or intentionally send NDP messages (refer to
1767  //RFC 4861, section 3.1)
1768  ancillary.ttl = NDP_HOP_LIMIT;
1769 
1770  //Send Router Solicitation message
1771  error = ipv6SendDatagram(interface, &pseudoHeader, buffer, offset,
1772  &ancillary);
1773 
1774  //Free previously allocated memory
1775  netBufferFree(buffer);
1776 
1777  //Return status code
1778  return error;
1779 }
1780 
1781 
1782 /**
1783  * @brief Send a Neighbor Solicitation message
1784  * @param[in] interface Underlying network interface
1785  * @param[in] targetIpAddr Target IPv6 address
1786  * @param[in] multicast Unicast or unicast Neighbor Solicitation message
1787  * @return Error code
1788  **/
1789 
1791  const Ipv6Addr *targetIpAddr, bool_t multicast)
1792 {
1793  error_t error;
1794  size_t offset;
1795  size_t length;
1796  NetBuffer *buffer;
1798  Ipv6PseudoHeader pseudoHeader;
1799  NetTxAncillary ancillary;
1800 
1801  //Multicast Neighbor Solicitation message?
1802  if(multicast)
1803  {
1804  //Compute the solicited-node multicast address that
1805  //corresponds to the target IPv6 address
1806  ipv6ComputeSolicitedNodeAddr(targetIpAddr, &pseudoHeader.destAddr);
1807  }
1808  else
1809  {
1810  //Unicast Neighbor Solicitation message
1811  pseudoHeader.destAddr = *targetIpAddr;
1812  }
1813 
1814  //Check whether the target address is a tentative address
1815  if(ipv6IsTentativeAddr(interface, targetIpAddr))
1816  {
1817  //The IPv6 source is set to the unspecified address
1818  pseudoHeader.srcAddr = IPV6_UNSPECIFIED_ADDR;
1819  }
1820  else
1821  {
1822  //Select the most appropriate source address to be used when sending
1823  //the Neighbor Solicitation message
1824  error = ipv6SelectSourceAddr(&interface, targetIpAddr,
1825  &pseudoHeader.srcAddr);
1826 
1827  //No address assigned to the interface?
1828  if(error)
1829  return error;
1830  }
1831 
1832  //The only defined option that may appear in a Neighbor Solicitation
1833  //message is the Source Link-Layer Address option
1835 
1836  //Allocate a memory buffer to hold the Neighbor Solicitation message
1837  buffer = ipAllocBuffer(length, &offset);
1838  //Failed to allocate memory?
1839  if(buffer == NULL)
1840  return ERROR_OUT_OF_MEMORY;
1841 
1842  //Point to the beginning of the message
1843  message = netBufferAt(buffer, offset, 0);
1844 
1845  //Format Neighbor Solicitation message
1847  message->code = 0;
1848  message->checksum = 0;
1849  message->reserved = 0;
1850  message->targetAddr = *targetIpAddr;
1851 
1852  //Length of the message, excluding any option
1853  length = sizeof(NdpNeighborSolMessage);
1854 
1855  //The Source Link-Layer Address option must not be included
1856  //when the source IPv6 address is the unspecified address
1857  if(!ipv6CompAddr(&pseudoHeader.srcAddr, &IPV6_UNSPECIFIED_ADDR))
1858  {
1859 #if (ETH_SUPPORT == ENABLED)
1860  NetInterface *logicalInterface;
1861 
1862  //Point to the logical interface
1863  logicalInterface = nicGetLogicalInterface(interface);
1864 
1865  //Add Source Link-Layer Address option
1867  &logicalInterface->macAddr, sizeof(MacAddr));
1868 #endif
1869  }
1870 
1871  //Adjust the length of the multi-part buffer
1872  netBufferSetLength(buffer, offset + length);
1873 
1874  //Format IPv6 pseudo header
1875  pseudoHeader.length = htonl(length);
1876  pseudoHeader.reserved[0] = 0;
1877  pseudoHeader.reserved[1] = 0;
1878  pseudoHeader.reserved[2] = 0;
1879  pseudoHeader.nextHeader = IPV6_ICMPV6_HEADER;
1880 
1881  //Calculate ICMPv6 header checksum
1882  message->checksum = ipCalcUpperLayerChecksumEx(&pseudoHeader,
1883  sizeof(Ipv6PseudoHeader), buffer, offset, length);
1884 
1885  //Total number of ICMP messages which this entity attempted to send
1886  IP_MIB_INC_COUNTER32(icmpv6Stats.icmpStatsOutMsgs, 1);
1887  //Increment per-message type ICMP counter
1888  IP_MIB_INC_COUNTER32(icmpv6MsgStatsTable.icmpMsgStatsOutPkts[ICMPV6_TYPE_NEIGHBOR_SOL], 1);
1889 
1890  //Debug message
1891  TRACE_INFO("Sending Neighbor Solicitation message (%" PRIuSIZE " bytes)...\r\n", length);
1892  //Dump message contents for debugging purpose
1894 
1895  //Additional options can be passed to the stack along with the packet
1896  ancillary = NET_DEFAULT_TX_ANCILLARY;
1897 
1898  //By setting the Hop Limit to 255, Neighbor Discovery is immune to off-link
1899  //senders that accidentally or intentionally send NDP messages (refer to
1900  //RFC 4861, section 3.1)
1901  ancillary.ttl = NDP_HOP_LIMIT;
1902 
1903  //Send Neighbor Solicitation message
1904  error = ipv6SendDatagram(interface, &pseudoHeader, buffer, offset,
1905  &ancillary);
1906 
1907  //Free previously allocated memory
1908  netBufferFree(buffer);
1909 
1910  //Return status code
1911  return error;
1912 }
1913 
1914 
1915 /**
1916  * @brief Send a Neighbor Advertisement message
1917  * @param[in] interface Underlying network interface
1918  * @param[in] targetIpAddr Target IPv6 address
1919  * @param[in] destIpAddr Destination IPv6 address
1920  * @return Error code
1921  **/
1922 
1924  const Ipv6Addr *targetIpAddr, const Ipv6Addr *destIpAddr)
1925 {
1926  error_t error;
1927  size_t offset;
1928  size_t length;
1929  NetBuffer *buffer;
1931  Ipv6PseudoHeader pseudoHeader;
1932  NetTxAncillary ancillary;
1933 #if (ETH_SUPPORT == ENABLED)
1934  NetInterface *logicalInterface;
1935 #endif
1936 
1937  //Destination IP address is the unspecified address?
1939  {
1940  //If the destination is the unspecified address, the node must
1941  //multicast the advertisement to the all-nodes address
1942  pseudoHeader.destAddr = IPV6_LINK_LOCAL_ALL_NODES_ADDR;
1943  }
1944  else
1945  {
1946  //Otherwise, the node must unicast the advertisement to the
1947  //destination IP address
1948  pseudoHeader.destAddr = *destIpAddr;
1949  }
1950 
1951  //Check whether the target address is a valid anycast address assigned
1952  //to the interface
1953  if(ipv6IsAnycastAddr(interface, targetIpAddr))
1954  {
1955  //Select the most appropriate source address to be used when sending
1956  //the Neighbor Advertisement message
1957  error = ipv6SelectSourceAddr(&interface, targetIpAddr,
1958  &pseudoHeader.srcAddr);
1959 
1960  //No address assigned to the interface?
1961  if(error)
1962  return error;
1963  }
1964  else
1965  {
1966  //Set the source IP address
1967  pseudoHeader.srcAddr = *targetIpAddr;
1968  }
1969 
1970  //The only defined option that may appear in a Neighbor Advertisement
1971  //message is the Target Link-Layer Address option
1973 
1974  //Allocate a memory buffer to hold the Neighbor Advertisement message
1975  buffer = ipAllocBuffer(length, &offset);
1976  //Failed to allocate memory?
1977  if(buffer == NULL)
1978  return ERROR_OUT_OF_MEMORY;
1979 
1980  //Point to the beginning of the message
1981  message = netBufferAt(buffer, offset, 0);
1982 
1983  //Format Neighbor Advertisement message
1985  message->code = 0;
1986  message->checksum = 0;
1987  message->reserved1 = 0;
1988  message->reserved2[0] = 0;
1989  message->reserved2[1] = 0;
1990  message->reserved2[2] = 0;
1991  message->targetAddr = *targetIpAddr;
1992 
1993  //The Router flag indicates that the sender is a router
1994  if(interface->ipv6Context.isRouter)
1995  {
1996  message->r = TRUE;
1997  }
1998  else
1999  {
2000  message->r = FALSE;
2001  }
2002 
2003  //If the destination is the unspecified address, the node must set
2004  //the Solicited flag to zero
2006  {
2007  message->s = FALSE;
2008  }
2009  else
2010  {
2011  message->s = TRUE;
2012  }
2013 
2014  //The Override flag should not be set in solicited advertisements
2015  //for anycast addresses
2016  if(ipv6IsAnycastAddr(interface, targetIpAddr))
2017  {
2018  message->o = FALSE;
2019  }
2020  else
2021  {
2022  message->o = TRUE;
2023  }
2024 
2025  //Length of the message, excluding any option
2026  length = sizeof(NdpNeighborAdvMessage);
2027 
2028 #if (ETH_SUPPORT == ENABLED)
2029  //Point to the logical interface
2030  logicalInterface = nicGetLogicalInterface(interface);
2031 
2032  //Add Target Link-Layer Address option
2034  &logicalInterface->macAddr, sizeof(MacAddr));
2035 #endif
2036 
2037  //Adjust the length of the multi-part buffer
2038  netBufferSetLength(buffer, offset + length);
2039 
2040  //Format IPv6 pseudo header
2041  pseudoHeader.length = htonl(length);
2042  pseudoHeader.reserved[0] = 0;
2043  pseudoHeader.reserved[1] = 0;
2044  pseudoHeader.reserved[2] = 0;
2045  pseudoHeader.nextHeader = IPV6_ICMPV6_HEADER;
2046 
2047  //Calculate ICMPv6 header checksum
2048  message->checksum = ipCalcUpperLayerChecksumEx(&pseudoHeader,
2049  sizeof(Ipv6PseudoHeader), buffer, offset, length);
2050 
2051  //Total number of ICMP messages which this entity attempted to send
2052  IP_MIB_INC_COUNTER32(icmpv6Stats.icmpStatsOutMsgs, 1);
2053  //Increment per-message type ICMP counter
2054  IP_MIB_INC_COUNTER32(icmpv6MsgStatsTable.icmpMsgStatsOutPkts[ICMPV6_TYPE_NEIGHBOR_ADV], 1);
2055 
2056  //Debug message
2057  TRACE_INFO("Sending Neighbor Advertisement message (%" PRIuSIZE " bytes)...\r\n", length);
2058  //Dump message contents for debugging purpose
2060 
2061  //Additional options can be passed to the stack along with the packet
2062  ancillary = NET_DEFAULT_TX_ANCILLARY;
2063 
2064  //By setting the Hop Limit to 255, Neighbor Discovery is immune to off-link
2065  //senders that accidentally or intentionally send NDP messages (refer to
2066  //RFC 4861, section 3.1)
2067  ancillary.ttl = NDP_HOP_LIMIT;
2068 
2069  //Send Neighbor Advertisement message
2070  error = ipv6SendDatagram(interface, &pseudoHeader, buffer, offset,
2071  &ancillary);
2072 
2073  //Free previously allocated memory
2074  netBufferFree(buffer);
2075 
2076  //Return status code
2077  return error;
2078 }
2079 
2080 
2081 /**
2082  * @brief Send a Redirect message
2083  * @param[in] interface Underlying network interface
2084  * @param[in] targetAddr IPv6 address that is a better first hop to use
2085  * for the destination address
2086  * @param[in] ipPacket Multi-part buffer that holds the IPv6 packet that
2087  * triggered the sending of the Redirect
2088  * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet
2089  * @return Error code
2090  **/
2091 
2093  const NetBuffer *ipPacket, size_t ipPacketOffset)
2094 {
2095  error_t error;
2096  size_t offset;
2097  size_t length;
2098  size_t ipPacketLen;
2099  size_t optionLen;
2100  size_t paddingLen;
2101  NetBuffer *buffer;
2103  NdpRedirectedHeaderOption *option;
2104  NdpNeighborCacheEntry *entry;
2105  Ipv6Header *ipHeader;
2106  Ipv6PseudoHeader pseudoHeader;
2107  NetTxAncillary ancillary;
2108  uint8_t padding[8];
2109 
2110  //Retrieve the length of the forwarded IPv6 packet
2111  ipPacketLen = netBufferGetLength(ipPacket) - ipPacketOffset;
2112 
2113  //Check the length of the IPv6 packet
2114  if(ipPacketLen < sizeof(Ipv6Header))
2115  return ERROR_INVALID_LENGTH;
2116 
2117  //Point to the header of the invoking packet
2118  ipHeader = netBufferAt(ipPacket, ipPacketOffset, 0);
2119  //Sanity check
2120  if(ipHeader == NULL)
2121  return ERROR_FAILURE;
2122 
2123  //The only defined options that may appear in a Redirect message are the
2124  //Target Link-Layer Address option and the Redirected Header option
2125  length = sizeof(NdpRedirectMessage) + sizeof(NdpLinkLayerAddrOption) +
2126  sizeof(NdpRedirectedHeaderOption);
2127 
2128  //Allocate a memory buffer to hold the Redirect message
2129  buffer = ipAllocBuffer(length, &offset);
2130  //Failed to allocate memory?
2131  if(buffer == NULL)
2132  return ERROR_OUT_OF_MEMORY;
2133 
2134  //Point to the beginning of the message
2135  message = netBufferAt(buffer, offset, 0);
2136 
2137  //Format Redirect message
2138  message->type = ICMPV6_TYPE_REDIRECT;
2139  message->code = 0;
2140  message->checksum = 0;
2141  message->reserved = 0;
2142  message->targetAddr = *targetAddr;
2143  message->destAddr = ipHeader->destAddr;
2144 
2145  //Length of the message, excluding any option
2146  length = sizeof(NdpRedirectMessage);
2147 
2148  //Search the Neighbor cache for the specified target address
2149  entry = ndpFindNeighborCacheEntry(interface, targetAddr);
2150 
2151  //Include the link-layer address of the target, if known
2152  if(entry != NULL)
2153  {
2154  //Add Target Link-Layer Address option
2156  &entry->macAddr, sizeof(MacAddr));
2157  }
2158 
2159  //Retrieve the length of the IPv6 packet that triggered the sending
2160  //of the Redirect
2161  ipPacketLen = netBufferGetLength(ipPacket) - ipPacketOffset;
2162 
2163  //Return as much of the forwarded IPv6 packet as can fit without the
2164  //redirect packet exceeding the minimum IPv6 MTU
2165  ipPacketLen = MIN(ipPacketLen, IPV6_DEFAULT_MTU -
2166  sizeof(NdpRedirectedHeaderOption) - length);
2167 
2168  //Length of the Redirected Header option in units of 8 bytes including
2169  //the type and length fields
2170  optionLen = (ipPacketLen + sizeof(NdpOption) + 7) / 8;
2171 
2172  //Add Redirected Header option
2173  option = (NdpRedirectedHeaderOption *) ((uint8_t *) message + length);
2174 
2175  //Format Redirected Header option
2176  option->type = NDP_OPT_REDIRECTED_HEADER;
2177  option->length = (uint8_t) optionLen;
2178  option->reserved1 = 0;
2179  option->reserved2 = 0;
2180 
2181  //Update the length of Redirect message
2182  length += sizeof(NdpRedirectedHeaderOption);
2183 
2184  //Adjust the length of the multi-part buffer
2185  netBufferSetLength(buffer, offset + length);
2186 
2187  //Copy the contents of the forwarded IPv6 packet
2188  error = netBufferConcat(buffer, ipPacket, ipPacketOffset, ipPacketLen);
2189 
2190  //Check status code
2191  if(!error)
2192  {
2193  //Options should be padded when necessary to ensure that they end on
2194  //their natural 64-bit boundaries
2195  if((ipPacketLen + sizeof(NdpRedirectedHeaderOption)) < (optionLen * 8))
2196  {
2197  //Determine the amount of padding data to append
2198  paddingLen = (optionLen * 8) - ipPacketLen -
2199  sizeof(NdpRedirectedHeaderOption);
2200 
2201  //Prepare padding data
2202  osMemset(padding, 0, paddingLen);
2203  //Append padding bytes
2204  error = netBufferAppend(buffer, padding, paddingLen);
2205  }
2206  }
2207 
2208  //Check status code
2209  if(!error)
2210  {
2211  //Get the length of the resulting message
2212  length = netBufferGetLength(buffer) - offset;
2213 
2214  //Format IPv6 pseudo header
2215  pseudoHeader.srcAddr = interface->ipv6Context.addrList[0].addr;
2216  pseudoHeader.destAddr = ipHeader->srcAddr;
2217  pseudoHeader.length = htonl(length);
2218  pseudoHeader.reserved[0] = 0;
2219  pseudoHeader.reserved[1] = 0;
2220  pseudoHeader.reserved[2] = 0;
2221  pseudoHeader.nextHeader = IPV6_ICMPV6_HEADER;
2222 
2223  //Message checksum calculation
2224  message->checksum = ipCalcUpperLayerChecksumEx(&pseudoHeader,
2225  sizeof(Ipv6PseudoHeader), buffer, offset, length);
2226 
2227  //Total number of ICMP messages which this entity attempted to send
2228  IP_MIB_INC_COUNTER32(icmpv6Stats.icmpStatsOutMsgs, 1);
2229  //Increment per-message type ICMP counter
2230  IP_MIB_INC_COUNTER32(icmpv6MsgStatsTable.icmpMsgStatsOutPkts[ICMPV6_TYPE_REDIRECT], 1);
2231 
2232  //Debug message
2233  TRACE_INFO("Sending Redirect message (%" PRIuSIZE " bytes)...\r\n", length);
2234  //Dump message contents for debugging purpose
2236 
2237  //Additional options can be passed to the stack along with the packet
2238  ancillary = NET_DEFAULT_TX_ANCILLARY;
2239 
2240  //By setting the Hop Limit to 255, Neighbor Discovery is immune to off-link
2241  //senders that accidentally or intentionally send NDP messages (refer to
2242  //RFC 4861, section 3.1)
2243  ancillary.ttl = NDP_HOP_LIMIT;
2244 
2245  //Send Redirect message
2246  error = ipv6SendDatagram(interface, &pseudoHeader, buffer, offset,
2247  &ancillary);
2248  }
2249 
2250  //Free previously allocated memory
2251  netBufferFree(buffer);
2252 
2253  //Return status code
2254  return error;
2255 }
2256 
2257 
2258 /**
2259  * @brief Dump Router Solicitation message for debugging purpose
2260  * @param[in] message Router Solicitation message
2261  **/
2262 
2264 {
2265  //Dump Router Solicitation message
2266  TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
2267  TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
2268  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
2269 }
2270 
2271 
2272 /**
2273  * @brief Dump Router Advertisement message for debugging purpose
2274  * @param[in] message Router Advertisement message
2275  **/
2276 
2278 {
2279  //Dump Router Advertisement message
2280  TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
2281  TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
2282  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
2283  TRACE_DEBUG(" Cur Hop Limit = %" PRIu8 "\r\n", message->curHopLimit);
2284  TRACE_DEBUG(" M = %" PRIu8 "\r\n", message->m);
2285  TRACE_DEBUG(" O = %" PRIu8 "\r\n", message->o);
2286  TRACE_DEBUG(" Router Lifetime = %" PRIu16 "\r\n", ntohs(message->routerLifetime));
2287  TRACE_DEBUG(" Reachable Time = %" PRIu32 "\r\n", ntohl(message->reachableTime));
2288  TRACE_DEBUG(" Retrans Timer = %" PRIu32 "\r\n", ntohl(message->retransTimer));
2289 }
2290 
2291 
2292 /**
2293  * @brief Dump Neighbor Solicitation message for debugging purpose
2294  * @param[in] message Neighbor Solicitation message
2295  **/
2296 
2298 {
2299  //Dump Neighbor Solicitation message
2300  TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
2301  TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
2302  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
2303  TRACE_DEBUG(" Target Address = %s\r\n", ipv6AddrToString(&message->targetAddr, NULL));
2304 }
2305 
2306 
2307 /**
2308  * @brief Dump Neighbor Advertisement message for debugging purpose
2309  * @param[in] message Neighbor Advertisement message
2310  **/
2311 
2313 {
2314  //Dump Neighbor Advertisement message
2315  TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
2316  TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
2317  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
2318  TRACE_DEBUG(" R = %" PRIu8 "\r\n", message->r);
2319  TRACE_DEBUG(" S = %" PRIu8 "\r\n", message->s);
2320  TRACE_DEBUG(" O = %" PRIu8 "\r\n", message->o);
2321  TRACE_DEBUG(" Target Address = %s\r\n", ipv6AddrToString(&message->targetAddr, NULL));
2322 }
2323 
2324 
2325 /**
2326  * @brief Dump Redirect message for debugging purpose
2327  * @param[in] message Redirect message
2328  **/
2329 
2331 {
2332  //Dump Neighbor Advertisement message
2333  TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
2334  TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
2335  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
2336  TRACE_DEBUG(" Target Address = %s\r\n", ipv6AddrToString(&message->targetAddr, NULL));
2337  TRACE_DEBUG(" Destination Address = %s\r\n", ipv6AddrToString(&message->destAddr, NULL));
2338 }
2339 
2340 #endif
@ IPV6_ADDR_STATE_TENTATIVE
An address whose uniqueness on a link is being verified.
Definition: ipv6.h:174
NdpNeighborCacheEntry * ndpFindNeighborCacheEntry(NetInterface *interface, const Ipv6Addr *ipAddr)
Search the Neighbor cache for a given IPv6 address.
Definition: ndp_cache.c:154
char_t * ipv6AddrToString(const Ipv6Addr *ipAddr, char_t *str)
Convert a binary IPv6 address to a string representation.
Definition: ipv6.c:2339
IPv6 (Internet Protocol Version 6)
void ipv6AddDefaultRouter(NetInterface *interface, const Ipv6Addr *addr, uint16_t lifetime, uint8_t preference)
Add a new entry to the Default Router List.
Definition: ipv6_misc.c:540
NetBuffer * ipAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold an IP packet.
Definition: ip.c:710
int bool_t
Definition: compiler_port.h:61
@ ERROR_NOT_FOUND
Definition: error.h:148
const NetTxAncillary NET_DEFAULT_TX_ANCILLARY
Definition: net_misc.c:72
#define NDP_HOP_LIMIT
Definition: ndp.h:199
@ NDP_STATE_STALE
Definition: ndp.h:252
Helper functions for NDP (Neighbor Discovery Protocol)
#define netMutex
Definition: net_legacy.h:195
#define NDP_MAX_PENDING_PACKETS
Definition: ndp.h:67
@ NDP_OPT_MTU
Definition: ndp.h:220
void ndpUpdateAddrList(NetInterface *interface)
Manage the lifetime of IPv6 addresses.
Definition: ndp_misc.c:98
#define IP_MIB_INC_COUNTER32(name, value)
Definition: ip_mib_module.h:46
void ndpDumpRouterSolMessage(const NdpRouterSolMessage *message)
Dump Router Solicitation message for debugging purpose.
Definition: ndp.c:2263
void ipv6RemoveDefaultRouter(NetInterface *interface, const Ipv6Addr *addr)
Remove an entry from the Default Router List.
Definition: ipv6_misc.c:607
void ndpTick(NetInterface *interface)
NDP timer handler.
Definition: ndp.c:547
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
uint8_t message[]
Definition: chap.h:154
uint32_t reachableTime
The time a node assumes a neighbor is reachable.
Definition: ndp.h:581
error_t ndpSendRedirect(NetInterface *interface, const Ipv6Addr *targetAddr, const NetBuffer *ipPacket, size_t ipPacketOffset)
Send a Redirect message.
Definition: ndp.c:2092
NetTxAncillary ancillary
Additional options.
Definition: ndp.h:540
bool_t rtrAdvReceived
Valid RA message received.
Definition: ndp.h:589
#define TRUE
Definition: os_port.h:50
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:605
NdpDestCacheEntry * ndpFindDestCacheEntry(NetInterface *interface, const Ipv6Addr *destAddr)
Search the Destination Cache for a given destination address.
Definition: ndp_cache.c:503
#define NDP_NEIGHBOR_CACHE_SIZE
Definition: ndp.h:53
@ NDP_OPT_SOURCE_LINK_LAYER_ADDR
Definition: ndp.h:216
Ipv6Addr addr
IPv6 address.
Definition: ipv6.h:421
#define NDP_RTR_SOLICITATION_INTERVAL
Definition: ndp.h:130
NdpRedirectMessage
Definition: ndp.h:367
@ ERROR_OUT_OF_RESOURCES
Definition: error.h:64
#define Ipv6Header
Definition: ipv6.h:36
systime_t rtrSolicitationInterval
Time interval between retransmissions of RS messages.
Definition: ndp.h:586
Ipv6Addr
Definition: ipv6.h:260
uint_t queueSize
Number of queued packets.
Definition: ndp.h:558
Neighbor cache entry.
Definition: ndp.h:549
Ipv6Addr targetAddr
Definition: ndp.h:323
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
bool_t ipv6IsTentativeAddr(NetInterface *interface, const Ipv6Addr *ipAddr)
Check whether an IPv6 address is a tentative address.
Definition: ipv6_misc.c:1100
#define NDP_MAX_RTR_SOLICITATIONS
Definition: ndp.h:137
#define ipv6CompAddr(ipAddr1, ipAddr2)
Definition: ipv6.h:127
systime_t minRtrSolicitationDelay
Minimum delay before transmitting the first RS message.
Definition: ndp.h:584
@ IPV6_ICMPV6_HEADER
Definition: ipv6.h:193
error_t ndpSendNeighborSol(NetInterface *interface, const Ipv6Addr *targetIpAddr, bool_t multicast)
Send a Neighbor Solicitation message.
Definition: ndp.c:1790
@ NDP_STATE_NONE
Definition: ndp.h:249
error_t ndpSetReachableTime(NetInterface *interface, systime_t reachableTime)
Configure the NDP reachable time.
Definition: ndp.c:141
Ipv6Addr destAddr
Destination IPv6 address.
Definition: ndp.h:568
#define timeCompare(t1, t2)
Definition: os_port.h:40
size_t pathMtu
Path MTU.
Definition: ndp.h:570
size_t offset
Offset to the first byte of the packet.
Definition: ndp.h:539
IPv6 Stateless Address Autoconfiguration.
@ IPV6_ADDR_STATE_INVALID
An address that is not assigned to any interface.
Definition: ipv6.h:173
#define NDP_DELAY_FIRST_PROBE_TIME
Definition: ndp.h:193
uint8_t ipPacket[]
Definition: ndp.h:431
void ndpDumpNeighborSolMessage(const NdpNeighborSolMessage *message)
Dump Neighbor Solicitation message for debugging purpose.
Definition: ndp.c:2297
error_t netBufferConcat(NetBuffer *dest, const NetBuffer *src, size_t srcOffset, size_t length)
Concatenate two multi-part buffers.
Definition: net_mem.c:460
#define ipv6IsMulticastAddr(ipAddr)
Definition: ipv6.h:139
systime_t ndpTickCounter
Definition: ndp.c:59
@ ERROR_IN_PROGRESS
Definition: error.h:214
void ndpLinkChangeEvent(NetInterface *interface)
Callback function for link change event.
Definition: ndp.c:638
#define FALSE
Definition: os_port.h:46
@ NDP_OPT_TARGET_LINK_LAYER_ADDR
Definition: ndp.h:217
uint_t dupAddrDetectTransmits
Maximum number of NS messages sent while performing DAD.
Definition: ndp.h:583
void ndpProcessRedirect(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, const NetRxAncillary *ancillary)
Redirect message processing.
Definition: ndp.c:1460
ICMPv6 (Internet Control Message Protocol Version 6)
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define htonl(value)
Definition: cpu_endian.h:414
NetInterface * nicGetPhysicalInterface(NetInterface *interface)
Retrieve physical interface.
Definition: nic.c:85
uint32_t netGenerateRandRange(uint32_t min, uint32_t max)
Generate a random value in the specified range.
Definition: net_misc.c:963
MacAddr macAddr
Link layer address associated with the IPv6 address.
Definition: ndp.h:552
NdpRouterAdvMessage
Definition: ndp.h:310
error_t
Error codes.
Definition: error.h:43
NdpNeighborSolMessage
Definition: ndp.h:325
#define Ipv6PseudoHeader
Definition: ipv6.h:42
@ ICMPV6_TYPE_REDIRECT
Definition: icmpv6.h:66
systime_t timestamp
Timestamp to manage entry lifetime.
Definition: ndp.h:571
error_t ipv6SelectSourceAddr(NetInterface **interface, const Ipv6Addr *destAddr, Ipv6Addr *srcAddr)
IPv6 source address selection.
Definition: ipv6_misc.c:870
NDP context.
Definition: ndp.h:580
NdpOption
Definition: ndp.h:379
systime_t timestamp
Timestamp to manage retransmissions.
Definition: ndp.h:590
@ ERROR_INVALID_ADDRESS
Definition: error.h:103
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
char_t * macAddrToString(const MacAddr *macAddr, char_t *str)
Convert a MAC address to a dash delimited string.
Definition: ethernet.c:919
void slaacParseRouterAdv(SlaacContext *context, NdpRouterAdvMessage *message, size_t length)
Parse Router Advertisement message.
Definition: slaac_misc.c:104
NdpNeighborCacheEntry * ndpCreateNeighborCacheEntry(NetInterface *interface)
Create a new entry in the Neighbor cache.
Definition: ndp_cache.c:72
#define NDP_RETRANS_TIMER
Definition: ndp.h:186
const Ipv6Addr IPV6_LINK_LOCAL_ALL_NODES_ADDR
Definition: ipv6.c:74
NdpNeighborAdvMessage
Definition: ndp.h:351
#define NetRxAncillary
Definition: net_misc.h:40
NdpDestCacheEntry * ndpCreateDestCacheEntry(NetInterface *interface)
Create a new entry in the Destination Cache.
Definition: ndp_cache.c:452
#define NetInterface
Definition: net.h:36
void netBufferFree(NetBuffer *buffer)
Dispose a multi-part buffer.
Definition: net_mem.c:282
NdpMtuOption
Definition: ndp.h:445
@ ERROR_INVALID_LENGTH
Definition: error.h:111
uint_t ndpSendQueuedPackets(NetInterface *interface, NdpNeighborCacheEntry *entry)
Send packets that are waiting for address resolution.
Definition: ndp_cache.c:350
@ NDP_STATE_DELAY
Definition: ndp.h:253
Helper functions for IPv6.
@ ICMPV6_TYPE_NEIGHBOR_ADV
Definition: icmpv6.h:65
bool_t enable
Enable address resolution using Neighbor Discovery protocol.
Definition: ndp.h:592
#define NetTxAncillary
Definition: net_misc.h:36
const Ipv6Addr IPV6_UNSPECIFIED_ADDR
Definition: ipv6.c:66
NdpRouterSolMessage
Definition: ndp.h:278
error_t netBufferCopy(NetBuffer *dest, size_t destOffset, const NetBuffer *src, size_t srcOffset, size_t length)
Copy data between multi-part buffers.
Definition: net_mem.c:522
bool_t duplicate
The address is a duplicate.
Definition: ipv6.h:423
#define TRACE_INFO(...)
Definition: debug.h:105
uint8_t length
Definition: tcp.h:375
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
void ndpUpdateDefaultRouterList(NetInterface *interface)
Periodically update Default Router List.
Definition: ndp_misc.c:297
@ NDP_STATE_INCOMPLETE
Definition: ndp.h:250
#define MIN(a, b)
Definition: os_port.h:63
uint_t maxRtrSolicitations
Number of retransmissions for RS messages.
Definition: ndp.h:587
Neighbor and destination cache management.
#define ipv6IsSolicitedNodeAddr(ipAddr)
Definition: ipv6.h:143
#define NDP_MAX_RTR_SOLICITATION_DELAY
Definition: ndp.h:123
@ NDP_STATE_REACHABLE
Definition: ndp.h:251
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:455
MacAddr
Definition: ethernet.h:195
#define ipv6IsLinkLocalUnicastAddr(ipAddr)
Definition: ipv6.h:131
NdpRedirectedHeaderOption
Definition: ndp.h:432
NDP (Neighbor Discovery Protocol)
void ndpProcessNeighborSol(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, const NetRxAncillary *ancillary)
Neighbor Solicitation message processing.
Definition: ndp.c:966
NdpQueueItem queue[NDP_MAX_PENDING_PACKETS]
Packets waiting for address resolution to complete.
Definition: ndp.h:557
void ndpDumpNeighborAdvMessage(const NdpNeighborAdvMessage *message)
Dump Neighbor Advertisement message for debugging purpose.
Definition: ndp.c:2312
NetBuffer * netBufferAlloc(size_t length)
Allocate a multi-part buffer.
Definition: net_mem.c:243
void ndpProcessNeighborAdv(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, const NetRxAncillary *ancillary)
Neighbor Advertisement message processing.
Definition: ndp.c:1212
uint32_t systime_t
System time.
#define ntohs(value)
Definition: cpu_endian.h:421
void ndpFlushNeighborCache(NetInterface *interface)
Flush Neighbor cache.
Definition: ndp_cache.c:315
void ndpUpdateNeighborCache(NetInterface *interface)
Periodically update Neighbor cache.
Definition: ndp_cache.c:187
#define TRACE_WARNING(...)
Definition: debug.h:93
#define TRACE_DEBUG(...)
Definition: debug.h:119
uint32_t retransTimer
The time between retransmissions of NS messages.
Definition: ndp.h:582
error_t ndpEnable(NetInterface *interface, bool_t enable)
Enable address resolution using Neighbor Discovery protocol.
Definition: ndp.c:106
void ndpFlushDestCache(NetInterface *interface)
Flush Destination Cache.
Definition: ndp_cache.c:532
uint32_t time
error_t ndpInit(NetInterface *interface)
Neighbor cache initialization.
Definition: ndp.c:68
uint16_t ipCalcUpperLayerChecksumEx(const void *pseudoHeader, size_t pseudoHeaderLen, const NetBuffer *buffer, size_t offset, size_t length)
Calculate IP upper-layer checksum over a multi-part buffer.
Definition: ip.c:685
Ipv6Addr ipAddr
Unicast IPv6 address.
Definition: ndp.h:551
error_t ndpSendNeighborAdv(NetInterface *interface, const Ipv6Addr *targetIpAddr, const Ipv6Addr *destIpAddr)
Send a Neighbor Advertisement message.
Definition: ndp.c:1923
NdpLinkLayerAddrOption
Definition: ndp.h:391
@ ICMPV6_TYPE_ROUTER_SOL
Definition: icmpv6.h:62
#define IPV6_DEFAULT_MTU
Definition: ipv6.h:115
IPv6 address entry.
Definition: ipv6.h:420
NetInterface * srcInterface
Interface from which the packet has been received.
Definition: ndp.h:537
systime_t maxRtrSolicitationDelay
Maximum delay before transmitting the first RS message.
Definition: ndp.h:585
uint8_t n
@ ERROR_UNEXPECTED_STATE
Definition: error.h:99
const Ipv6Addr IPV6_LINK_LOCAL_ALL_ROUTERS_ADDR
Definition: ipv6.c:78
error_t ipv6SendDatagram(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send an IPv6 datagram.
Definition: ipv6.c:1713
IP MIB module.
error_t ndpEnqueuePacket(NetInterface *srcInterface, NetInterface *destInterface, const Ipv6Addr *ipAddr, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Enqueue an IPv6 packet waiting for address resolution.
Definition: ndp.c:457
error_t netBufferAppend(NetBuffer *dest, const void *src, size_t length)
Append data a multi-part buffer.
Definition: net_mem.c:604
#define IPV6_ADDR_LIST_SIZE
Definition: ipv6.h:65
NdpState state
Reachability state.
Definition: ndp.h:550
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
Destination cache entry.
Definition: ndp.h:567
#define NDP_DUP_ADDR_DETECT_TRANSMITS
Definition: ndp.h:158
Ipv6AddrState ipv6GetLinkLocalAddrState(NetInterface *interface)
Get the state of the link-local address.
Definition: ipv6.c:327
void * ndpGetOption(uint8_t *options, size_t length, uint8_t type)
Search a NDP message for a given option.
Definition: ndp_misc.c:653
@ NDP_OPT_REDIRECTED_HEADER
Definition: ndp.h:219
error_t ndpSetRetransTimer(NetInterface *interface, systime_t retransTimer)
Configure the time interval between retransmission of NS messages.
Definition: ndp.c:189
@ NDP_OPT_PREFIX_INFORMATION
Definition: ndp.h:218
error_t netBufferSetLength(NetBuffer *buffer, size_t length)
Adjust the length of a multi-part buffer.
Definition: net_mem.c:322
uint32_t reachableTime
Definition: ndp.h:307
bool_t ipv6IsAnycastAddr(NetInterface *interface, const Ipv6Addr *ipAddr)
Check whether an IPv6 address is an anycast address.
Definition: ipv6_misc.c:1064
uint_t retransmitCount
Retransmission counter.
Definition: ndp.h:556
NetBuffer * buffer
Packet waiting for address resolution.
Definition: ndp.h:538
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:130
#define NDP_REACHABLE_TIME
Definition: ndp.h:179
error_t ipv6ComputeSolicitedNodeAddr(const Ipv6Addr *ipAddr, Ipv6Addr *solicitedNodeAddr)
Form a solicited-node address from an IPv6 address.
Definition: ipv6_misc.c:1365
error_t ndpSendRouterSol(NetInterface *interface)
Send a Router Solicitation message.
Definition: ndp.c:1670
systime_t timeout
Timeout value.
Definition: ndp.h:591
error_t ndpCheckOptions(const uint8_t *options, size_t length)
Check NDP message options.
Definition: ndp_misc.c:696
#define NDP_MIN_RTR_SOLICITATION_DELAY
Definition: ndp.h:116
void ndpDumpRouterAdvMessage(const NdpRouterAdvMessage *message)
Dump Router Advertisement message for debugging purpose.
Definition: ndp.c:2277
void * netBufferAt(const NetBuffer *buffer, size_t offset, size_t length)
Returns a pointer to a data segment.
Definition: net_mem.c:418
Ipv4Addr ipAddr
Definition: ipcp.h:105
Helper functions for SLAAC.
void ndpUpdatePrefixList(NetInterface *interface)
Periodically update Prefix List.
Definition: ndp_misc.c:261
error_t ndpResolve(NetInterface *interface, const Ipv6Addr *ipAddr, MacAddr *macAddr)
Address resolution using Neighbor Discovery protocol.
Definition: ndp.c:357
void ndpParsePrefixInfoOption(NetInterface *interface, NdpPrefixInfoOption *option)
Parse Prefix Information Option.
Definition: ndp_misc.c:55
void ndpChangeState(NdpNeighborCacheEntry *entry, NdpState newState)
Update Neighbor cache entry state.
Definition: ndp_cache.c:53
@ IPV6_ADDR_STATE_PREFERRED
An address assigned to an interface whose use is unrestricted.
Definition: ipv6.h:175
uint_t rtrSolicitationCount
Retransmission counter for RS messages.
Definition: ndp.h:588
Ipv6AddrState state
IPv6 address state.
Definition: ipv6.h:422
error_t ndpRemoveStaticEntry(NetInterface *interface, const Ipv6Addr *ipAddr)
Remove a static entry from the Neighbor cache.
Definition: ndp.c:312
#define PRIuSIZE
@ NIC_TYPE_6LOWPAN
6LoWPAN interface
Definition: nic.h:87
unsigned int uint_t
Definition: compiler_port.h:57
NdpPrefixInfoOption
Definition: ndp.h:418
#define osMemset(p, value, length)
Definition: os_port.h:138
error_t ndpAddStaticEntry(NetInterface *interface, const Ipv6Addr *ipAddr, const MacAddr *macAddr)
Add a static entry in the Neighbor cache.
Definition: ndp.c:238
TCP/IP stack core.
NetInterface * nicGetLogicalInterface(NetInterface *interface)
Retrieve logical interface.
Definition: nic.c:53
@ ICMPV6_TYPE_NEIGHBOR_SOL
Definition: icmpv6.h:64
@ NDP_STATE_PERMANENT
Definition: ndp.h:255
@ NDP_STATE_PROBE
Definition: ndp.h:254
void ndpProcessRouterAdv(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, const NetRxAncillary *ancillary)
Router Advertisement message processing.
Definition: ndp.c:676
#define ntohl(value)
Definition: cpu_endian.h:422
uint32_t retransTimer
Definition: ndp.h:308
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:53
@ NO_ERROR
Success.
Definition: error.h:44
systime_t timeout
Timeout value.
Definition: ndp.h:555
Debugging facilities.
bool_t isRouter
A flag indicating whether the neighbor is a router or a host.
Definition: ndp.h:553
Ipv6Addr nextHop
IPv6 address of the next-hop neighbor.
Definition: ndp.h:569
systime_t osGetSystemTime(void)
Retrieve system time.
void ndpDumpRedirectMessage(const NdpRedirectMessage *message)
Dump Redirect message for debugging purpose.
Definition: ndp.c:2330
Ipv4Addr destIpAddr
Definition: ipcp.h:80