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