ndp_router_adv.c
Go to the documentation of this file.
1 /**
2  * @file ndp_router_adv.c
3  * @brief Router advertisement service
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneTCP Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @author Oryx Embedded SARL (www.oryx-embedded.com)
26  * @version 1.9.0
27  **/
28 
29 //Switch to the appropriate trace level
30 #define TRACE_LEVEL NDP_TRACE_LEVEL
31 
32 //Dependencies
33 #include "core/net.h"
34 #include "core/ip.h"
35 #include "ipv6/ipv6.h"
36 #include "ipv6/ipv6_misc.h"
37 #include "ipv6/icmpv6.h"
38 #include "ipv6/ndp.h"
39 #include "ipv6/ndp_cache.h"
40 #include "ipv6/ndp_misc.h"
41 #include "ipv6/ndp_router_adv.h"
42 #include "mibs/ip_mib_module.h"
43 #include "debug.h"
44 
45 //Check TCP/IP stack configuration
46 #if (IPV6_SUPPORT == ENABLED && NDP_ROUTER_ADV_SUPPORT == ENABLED)
47 
48 //Tick counter to handle periodic operations
50 
51 
52 /**
53  * @brief Initialize settings with default values
54  * @param[out] settings Structure that contains the RA service configuration variables
55  **/
56 
58 {
59  //Underlying network interface
60  settings->interface = netGetDefaultInterface();
61 
62  //The maximum time allowed between sending unsolicited multicast
63  //Router Advertisements from the interface
65 
66  //The minimum time allowed between sending unsolicited multicast
67  //Router Advertisements from the interface
69 
70  //The default value to be placed in the Cur Hop Limit field in the
71  //Router Advertisement messages sent by the router
72  settings->curHopLimit = 0;
73 
74  //The value to be placed in the Managed Address Configuration
75  //flag in the Router Advertisement
76  settings->managedFlag = FALSE;
77 
78  //The value to be placed in the Other Configuration flag
79  //in the Router Advertisement
80  settings->otherConfigFlag = FALSE;
81 
82  //The value to be placed in the Mobile IPv6 Home Agent
83  //flag in the Router Advertisement
84  settings->homeAgentFlag = FALSE;
85 
86  //The value to be placed in the Router Selection Preferences
87  //field in the Router Advertisement
89 
90  //The value to be placed in the Neighbor Discovery Proxy
91  //flag in the Router Advertisement
92  settings->proxyFlag = FALSE;
93 
94  //The value to be placed in the Router Lifetime field of
95  //Router Advertisements sent from the interface
96  settings->defaultLifetime = 3 * (NDP_MAX_RTR_ADVERT_INTERVAL / 1000);
97 
98  //The value to be placed in the Reachable Time field in the
99  //Router Advertisement messages sent by the router
100  settings->reachableTime = 0;
101 
102  //The value to be placed in the Retrans Timer field in the
103  //Router Advertisement messages sent by the router
104  settings->retransTimer = 0;
105 
106  //The value to be placed in the MTU option sent by the router
107  settings->linkMtu = 0;
108 
109  //A list of prefixes to be placed in Prefix Information options (PIO)
110  //in Router Advertisement messages sent from the interface
111  settings->prefixList = NULL;
112  settings->prefixListLength = 0;
113 
114  //A list of routes to be placed in Route Information options (RIO)
115  //in Router Advertisement messages sent from the interface
116  settings->routeList = NULL;
117  settings->routeListLength = 0;
118 
119  //A list of header compression contexts to be placed in the 6LoWPAN Context
120  //options (6CO) in Router Advertisement messages sent from the interface
121  settings->contextList = NULL;
122  settings->contextListLength = 0;
123 }
124 
125 
126 /**
127  * @brief RA service initialization
128  * @param[in] context Pointer to the RA service context
129  * @param[in] settings RA service configuration variables
130  * @return Error code
131  **/
132 
134  const NdpRouterAdvSettings *settings)
135 {
136  NetInterface *interface;
137 
138  //Debug message
139  TRACE_INFO("Initializing Router Advertisement service...\r\n");
140 
141  //Ensure the parameters are valid
142  if(!context || !settings)
144 
145  //Valid network interface?
146  if(!settings->interface)
148 
149  //Get exclusive access
151 
152  //Point to the underlying network interface
153  interface = settings->interface;
154 
155  //Clear the RA service context
156  memset(context, 0, sizeof(NdpRouterAdvContext));
157  //Save user settings
158  context->settings = *settings;
159 
160  //The RA service is currently disabled on the interface
161  context->running = FALSE;
162  //Attach the RA service context to the network interface
163  interface->ndpRouterAdvContext = context;
164 
165  //Release exclusive access
167 
168  //Successful initialization
169  return NO_ERROR;
170 }
171 
172 
173 /**
174  * @brief Start RA service
175  * @param[in] context Pointer to the RA service context
176  * @return Error code
177  **/
178 
180 {
181  error_t error;
182  NetInterface *interface;
183 
184  //Check parameter
185  if(context == NULL)
187 
188  //Debug message
189  TRACE_INFO("Starting Router Advertisement service...\r\n");
190 
191  //Get exclusive access
193 
194  //Check whether the service is running
195  if(!context->running)
196  {
197  //Point to the underlying network interface
198  interface = context->settings.interface;
199 
200  //Join the All-Routers multicast address
202 
203  //Successful membership registration?
204  if(!error)
205  {
206  //Reset variables
207  context->timestamp = osGetSystemTime();
208  context->timeout = 0;
209  context->routerAdvCount = 0;
210 
211  //Enable the router to forward packets to or from the interface
212  interface->ipv6Context.isRouter = TRUE;
213 
214  //Default Hop Limit value
215  if(context->settings.curHopLimit != 0)
216  interface->ipv6Context.curHopLimit = context->settings.curHopLimit;
217 
218  //The time a node assumes a neighbor is reachable
219  if(context->settings.reachableTime != 0)
220  interface->ndpContext.reachableTime = context->settings.reachableTime;
221 
222  //The time between retransmissions of NS messages
223  if(context->settings.retransTimer != 0)
224  interface->ndpContext.retransTimer = context->settings.retransTimer;
225 
226  //Start transmitting Router Advertisements
227  context->running = TRUE;
228  }
229  }
230  else
231  {
232  //The service is already running...
233  error = NO_ERROR;
234  }
235 
236  //Release exclusive access
238 
239  //Return status code
240  return error;
241 }
242 
243 
244 /**
245  * @brief Stop RA service
246  * @param[in] context Pointer to the RA service context
247  * @return Error code
248  **/
249 
251 {
252  error_t error;
253  NetInterface *interface;
254 
255  //Check parameter
256  if(context == NULL)
258 
259  //Debug message
260  TRACE_INFO("Stopping Router Advertisement service...\r\n");
261 
262  //Get exclusive access
264 
265  //Check whether the service is running
266  if(context->running)
267  {
268  //Point to the underlying network interface
269  interface = context->settings.interface;
270 
271  //The router should transmit one or more final multicast Router
272  //Advertisements with a Router Lifetime field of zero
273  ndpSendRouterAdv(context, 0);
274 
275  //Leave the All-Routers multicast address
277 
278  //Restore default parameters
279  interface->ipv6Context.curHopLimit = IPV6_DEFAULT_HOP_LIMIT;
280  interface->ndpContext.reachableTime = NDP_REACHABLE_TIME;
281  interface->ndpContext.retransTimer = NDP_RETRANS_TIMER;
282 
283  //Stop transmitting Router Advertisements
284  context->running = FALSE;
285  }
286  else
287  {
288  //The service is not running...
289  error = NO_ERROR;
290  }
291 
292  //Release exclusive access
294 
295  //Return status code
296  return error;
297 }
298 
299 
300 /**
301  * @brief RA service timer handler
302  * @param[in] context Pointer to the RA service context
303  **/
304 
306 {
307  systime_t time;
308  NetInterface *interface;
309  NdpRouterAdvSettings *settings;
310 
311  //Make sure the RA service has been properly instantiated
312  if(context == NULL)
313  return;
314 
315  //Point to the underlying network interface
316  interface = context->settings.interface;
317  //Point to the router configuration variables
318  settings = &context->settings;
319 
320  //Get current time
321  time = osGetSystemTime();
322 
323  //Make sure that the link is up and the service is running
324  if(interface->linkState && context->running)
325  {
326  //Make sure that a valid link-local address has been assigned to the
327  //interface
329  {
330  //Check current time
331  if(timeCompare(time, context->timestamp + context->timeout) >= 0)
332  {
333  //Send an unsolicited Router Advertisement
334  ndpSendRouterAdv(context, context->settings.defaultLifetime);
335 
336  //Save the time at which the message was sent
337  context->timestamp = time;
338 
339  //Whenever a multicast advertisement is sent from an interface, the
340  //timer is reset to a uniformly distributed random value between
341  //MinRtrAdvInterval and MaxRtrAdvInterval
342  context->timeout = netGetRandRange(settings->minRtrAdvInterval,
343  settings->maxRtrAdvInterval);
344 
345  //First Router Advertisements to be sent from this interface?
347  {
348  //For the first few advertisements sent from an interface when it
349  //becomes an advertising interface, the randomly chosen interval
350  //should not be greater than MAX_INITIAL_RTR_ADVERT_INTERVAL
352  }
353 
354  //Increment counter
355  context->routerAdvCount++;
356  }
357  }
358  }
359 }
360 
361 
362 /**
363  * @brief Callback function for link change event
364  * @param[in] context Pointer to the RA service context
365  **/
366 
368 {
369  NetInterface *interface;
370 
371  //Make sure the RA service has been properly instantiated
372  if(context == NULL)
373  return;
374 
375  //Point to the underlying network interface
376  interface = context->settings.interface;
377 
378  //Reset variables
379  context->timestamp = osGetSystemTime();
380  context->timeout = 0;
381  context->routerAdvCount = 0;
382 
383  //Default Hop Limit value
384  if(context->settings.curHopLimit != 0)
385  interface->ipv6Context.curHopLimit = context->settings.curHopLimit;
386 
387  //The time a node assumes a neighbor is reachable
388  if(context->settings.reachableTime != 0)
389  interface->ndpContext.reachableTime = context->settings.reachableTime;
390 
391  //The time between retransmissions of NS messages
392  if(context->settings.retransTimer != 0)
393  interface->ndpContext.retransTimer = context->settings.retransTimer;
394 }
395 
396 
397 /**
398  * @brief Router Solicitation message processing
399  * @param[in] interface Underlying network interface
400  * @param[in] pseudoHeader IPv6 pseudo header
401  * @param[in] buffer Multi-part buffer containing the Router Advertisement message
402  * @param[in] offset Offset to the first byte of the message
403  * @param[in] hopLimit Hop Limit field from IPv6 header
404  **/
405 
406 void ndpProcessRouterSol(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader,
407  const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
408 {
409  error_t error;
410  uint_t n;
411  size_t length;
412  systime_t time;
413  systime_t delay;
414  NdpRouterAdvContext *context;
416  NdpLinkLayerAddrOption *option;
417  NdpNeighborCacheEntry *entry;
418 
419  //Point to the RA service context
420  context = interface->ndpRouterAdvContext;
421 
422  //A host must silently discard any received Router Solicitation
423  if(context == NULL)
424  return;
425 
426  //Get current time
427  time = osGetSystemTime();
428 
429  //Retrieve the length of the message
430  length = netBufferGetLength(buffer) - offset;
431 
432  //Check the length of the Router Solicitation message
433  if(length < sizeof(NdpRouterSolMessage))
434  return;
435 
436  //Point to the beginning of the message
437  message = netBufferAt(buffer, offset);
438  //Sanity check
439  if(message == NULL)
440  return;
441 
442  //Debug message
443  TRACE_INFO("Router Solicitation message received (%" PRIuSIZE " bytes)...\r\n",
444  length);
445 
446  //Dump message contents for debugging purpose
448 
449  //The IPv6 Hop Limit field must have a value of 255 to ensure that the
450  //packet has not been forwarded by a router
451  if(hopLimit != NDP_HOP_LIMIT)
452  return;
453 
454  //ICMPv6 Code must be 0
455  if(message->code)
456  return;
457 
458  //Calculate the length of the Options field
459  length -= sizeof(NdpRouterSolMessage);
460 
461  //Parse Options field
462  error = ndpCheckOptions(message->options, length);
463  //All included options must have a length that is greater than zero
464  if(error)
465  return;
466 
467  //Search for the Source Link-Layer Address option
468  option = ndpGetOption(message->options,
470 
471  //Source Link-Layer Address option found?
472  if(option != NULL && option->length == 1)
473  {
474  //Debug message
475  TRACE_DEBUG(" Source Link-Layer Address = %s\r\n",
476  macAddrToString(&option->linkLayerAddr, NULL));
477 
478  //The Source Link-Layer Address option must not be included when the
479  //source IP address is the unspecified address
480  if(ipv6CompAddr(&pseudoHeader->srcAddr, &IPV6_UNSPECIFIED_ADDR))
481  return;
482 
483  //Search the Neighbor Cache for the source address of the solicitation
484  entry = ndpFindNeighborCacheEntry(interface, &pseudoHeader->srcAddr);
485 
486  //No matching entry has been found?
487  if(!entry)
488  {
489  //Create an entry
490  entry = ndpCreateNeighborCacheEntry(interface);
491 
492  //Neighbor Cache entry successfully created?
493  if(entry)
494  {
495  //Record the IPv6 and the corresponding MAC address
496  entry->ipAddr = pseudoHeader->srcAddr;
497  entry->macAddr = option->linkLayerAddr;
498  //The IsRouter flag must be set to FALSE
499  entry->isRouter = FALSE;
500  //Save current time
501  entry->timestamp = time;
502  //Enter the STALE state
503  entry->state = NDP_STATE_STALE;
504  }
505  }
506  else
507  {
508  //If a Neighbor Cache entry for the solicitation's sender exists the
509  //entry's IsRouter flag must be set to FALSE
510  entry->isRouter = FALSE;
511 
512  //INCOMPLETE state?
513  if(entry->state == NDP_STATE_INCOMPLETE)
514  {
515  //Record link-layer address
516  entry->macAddr = option->linkLayerAddr;
517  //Send all the packets that are pending for transmission
518  n = ndpSendQueuedPackets(interface, entry);
519  //Save current time
520  entry->timestamp = time;
521 
522  //Check whether any packets have been sent
523  if(n > 0)
524  {
525  //Start delay timer
527  //Switch to the DELAY state
528  entry->state = NDP_STATE_DELAY;
529  }
530  else
531  {
532  //Enter the STALE state
533  entry->state = NDP_STATE_STALE;
534  }
535  }
536  //REACHABLE, STALE, DELAY or PROBE state?
537  else
538  {
539  //Different link-layer address than cached?
540  if(!macCompAddr(&entry->macAddr, &option->linkLayerAddr))
541  {
542  //Update link-layer address
543  entry->macAddr = option->linkLayerAddr;
544  //Save current time
545  entry->timestamp = time;
546  //Enter the STALE state
547  entry->state = NDP_STATE_STALE;
548  }
549  }
550  }
551  }
552 
553  //Upon receipt of a Router Solicitation, compute a random delay within the
554  //range 0 through MAX_RA_DELAY_TIME
556 
557  //If the computed value corresponds to a time later than the time the next
558  //multicast Router Advertisement is scheduled to be sent, ignore the random
559  //delay and send the advertisement at the already-scheduled time
560  if(timeCompare(time + delay, context->timestamp + context->timeout) > 0)
561  return;
562 
563  //Check whether the router sent a multicast Router Advertisement (solicited
564  //or unsolicited) within the last MIN_DELAY_BETWEEN_RAS seconds
566  {
567  //Schedule the advertisement to be sent at a time corresponding to
568  //MIN_DELAY_BETWEEN_RAS plus the random value after the previous
569  //advertisement was sent. This ensures that the multicast Router
570  //Advertisements are rate limited
571  context->timeout = NDP_MIN_DELAY_BETWEEN_RAS + delay;
572  }
573  else
574  {
575  //Schedule the sending of a Router Advertisement at the time given by the
576  //random value
577  context->timeout = time + delay - context->timestamp;
578  }
579 }
580 
581 
582 /**
583  * @brief Send a Router Advertisement message
584  * @param[in] context Pointer to the RA service context
585  * @param[in] routerLifetime Router Lifetime field
586  * @return Error code
587  **/
588 
590 {
591  error_t error;
592  uint_t i;
593  uint32_t n;
594  size_t offset;
595  size_t length;
596  NetBuffer *buffer;
597  NetInterface *interface;
599  NdpRouterAdvSettings *settings;
600  Ipv6PseudoHeader pseudoHeader;
601 #if (ETH_SUPPORT == ENABLED)
602  NetInterface *logicalInterface;
603 #endif
604 
605  //Point to the underlying network interface
606  interface = context->settings.interface;
607  //Point to the router configuration variables
608  settings = &context->settings;
609 
610  //The destination address is typically the all-nodes multicast address
611  pseudoHeader.destAddr = IPV6_LINK_LOCAL_ALL_NODES_ADDR;
612 
613  //Routers must use their link-local address as the source for Router
614  //Advertisement messages so that hosts can uniquely identify routers
615  error = ipv6SelectSourceAddr(&interface,
616  &pseudoHeader.destAddr, &pseudoHeader.srcAddr);
617 
618  //No link-local address assigned to the interface?
619  if(error)
620  return error;
621 
622  //Compute the maximum size of the Router Advertisement message
623  length = sizeof(NdpRouterAdvMessage) +
624  sizeof(NdpLinkLayerAddrOption) + sizeof(NdpMtuOption) +
625  settings->prefixListLength * sizeof(NdpPrefixInfoOption) +
626  settings->routeListLength * sizeof(NdpRouteInfoOption) +
627  settings->contextListLength * sizeof(NdpContextOption);
628 
629  //Sanity check
630  if((length + sizeof(Ipv6Header)) > IPV6_DEFAULT_MTU)
631  return ERROR_FAILURE;
632 
633  //Allocate a memory buffer to hold the Router Advertisement message
634  buffer = ipAllocBuffer(length, &offset);
635  //Failed to allocate memory?
636  if(buffer == NULL)
637  return ERROR_OUT_OF_MEMORY;
638 
639  //Point to the beginning of the message
640  message = netBufferAt(buffer, offset);
641 
642  //Format Router Advertisement message
644  message->code = 0;
645  message->checksum = 0;
646  message->curHopLimit = settings->curHopLimit;
647  message->m = settings->managedFlag;
648  message->o = settings->otherConfigFlag;
649  message->h = settings->homeAgentFlag;
650  message->prf = settings->preference;
651  message->p = settings->proxyFlag;
652  message->reserved = 0;
653  message->routerLifetime = htons(routerLifetime);
654  message->reachableTime = htonl(settings->reachableTime);
655  message->retransTimer = htonl(settings->retransTimer);
656 
657  //If the Router Lifetime is zero, the preference value must be set to zero
658  //by the sender
659  if(routerLifetime == 0)
661 
662  //Length of the message, excluding any option
663  length = sizeof(NdpRouterAdvMessage);
664 
665 #if (ETH_SUPPORT == ENABLED)
666  //Point to the logical interface
667  logicalInterface = nicGetLogicalInterface(interface);
668 
669  //Check whether a MAC address has been assigned to the interface
670  if(!macCompAddr(&logicalInterface->macAddr, &MAC_UNSPECIFIED_ADDR))
671  {
672  //Add Source Link-Layer Address option
674  &logicalInterface->macAddr, sizeof(MacAddr));
675  }
676 #endif
677 
678  //A value of zero indicates that no MTU option is sent
679  if(settings->linkMtu > 0)
680  {
681  NdpMtuOption mtuOption;
682 
683  //The MTU option specifies the recommended MTU for the link
684  mtuOption.reserved = 0;
685  mtuOption.mtu = htonl(settings->linkMtu);
686 
687  //Add MTU option
689  (uint8_t *) &mtuOption + sizeof(NdpOption),
690  sizeof(NdpMtuOption) - sizeof(NdpOption));
691  }
692 
693  //Loop through the list of IPv6 prefixes
694  for(i = 0; i < settings->prefixListLength; i++)
695  {
696  NdpPrefixInfoOption prefixInfoOption;
697 
698  //The Prefix Information option provide hosts with on-link prefixes and
699  //prefixes for Address Autoconfiguration
700  prefixInfoOption.prefixLength = settings->prefixList[i].length;
701  prefixInfoOption.l = settings->prefixList[i].onLinkFlag;
702  prefixInfoOption.a = settings->prefixList[i].autonomousFlag;
703  prefixInfoOption.r = 0;
704  prefixInfoOption.reserved1 = 0;
705  prefixInfoOption.validLifetime = htonl(settings->prefixList[i].validLifetime);
706  prefixInfoOption.preferredLifetime = htonl(settings->prefixList[i].preferredLifetime);
707  prefixInfoOption.reserved2 = 0;
708  prefixInfoOption.prefix = settings->prefixList[i].prefix;
709 
710  //Add Prefix Information option (PIO)
712  (uint8_t *) &prefixInfoOption + sizeof(NdpOption),
713  sizeof(NdpPrefixInfoOption) - sizeof(NdpOption));
714  }
715 
716  //Loop through the list of routes
717  for(i = 0; i < settings->routeListLength; i++)
718  {
719  NdpRouteInfoOption routeInfoOption;
720 
721  //The Route Information option specifies prefixes that are reachable via
722  //the router
723  routeInfoOption.prefixLength = settings->routeList[i].length;
724  routeInfoOption.reserved1 = 0;
725  routeInfoOption.prf = settings->routeList[i].preference;
726  routeInfoOption.reserved2 = 0;
727  routeInfoOption.routeLifetime = htonl(settings->routeList[i].routeLifetime);
728  routeInfoOption.prefix = settings->routeList[i].prefix;
729 
730  //Add Route Information option (RIO)
732  (uint8_t *) &routeInfoOption + sizeof(NdpOption),
733  sizeof(NdpRouteInfoOption) - sizeof(NdpOption));
734  }
735 
736  //Loop through the list of 6LoWPAN compression contexts
737  for(i = 0; i < settings->contextListLength; i++)
738  {
739  NdpContextOption contextOption;
740 
741  //The 6LoWPAN Context option (6CO) carries prefix information for LoWPAN
742  //header compression
743  contextOption.contextLength = settings->contextList[i].length;
744  contextOption.reserved1 = 0;
745  contextOption.c = settings->contextList[i].compression;
746  contextOption.cid = settings->contextList[i].cid;
747  contextOption.reserved2 = 0;
748  contextOption.validLifetime = htons(settings->contextList[i].validLifetime);
749  contextOption.contextPrefix = settings->contextList[i].prefix;
750 
751  //Calculate the length of the option in bytes
752  n = sizeof(NdpContextOption) - sizeof(Ipv6Addr) + (contextOption.contextLength / 8);
753 
754  //Add 6LoWPAN Context option (6CO)
756  (uint8_t *) &contextOption + sizeof(NdpOption), n - sizeof(NdpOption));
757  }
758 
759  //Adjust the length of the multi-part buffer
760  netBufferSetLength(buffer, offset + length);
761 
762  //Format IPv6 pseudo header
763  pseudoHeader.length = htonl(length);
764  pseudoHeader.reserved = 0;
765  pseudoHeader.nextHeader = IPV6_ICMPV6_HEADER;
766 
767  //Calculate ICMPv6 header checksum
768  message->checksum = ipCalcUpperLayerChecksumEx(&pseudoHeader,
769  sizeof(Ipv6PseudoHeader), buffer, offset, length);
770 
771  //Total number of ICMP messages which this entity attempted to send
772  IP_MIB_INC_COUNTER32(icmpv6Stats.icmpStatsOutMsgs, 1);
773  //Increment per-message type ICMP counter
774  IP_MIB_INC_COUNTER32(icmpv6MsgStatsTable.icmpMsgStatsOutPkts[ICMPV6_TYPE_ROUTER_ADV], 1);
775 
776  //Debug message
777  TRACE_INFO("Sending Router Advertisement message (%" PRIuSIZE " bytes)...\r\n",
778  length);
779 
780  //Dump message contents for debugging purpose
782 
783  //Send Router Advertisement message
784  error = ipv6SendDatagram(interface, &pseudoHeader, buffer, offset, NDP_HOP_LIMIT);
785 
786  //Free previously allocated memory
787  netBufferFree(buffer);
788  //Return status code
789  return error;
790 }
791 
792 #endif
void ndpRouterAdvGetDefaultSettings(NdpRouterAdvSettings *settings)
Initialize settings with default values.
error_t ndpCheckOptions(const uint8_t *options, size_t length)
Check NDP message options.
Definition: ndp_misc.c:678
NdpRouterAdvSettings settings
RA service settings.
uint32_t systime_t
Definition: compiler_port.h:44
error_t ipv6SendDatagram(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Send an IPv6 datagram.
Definition: ipv6.c:1574
void ndpProcessRouterSol(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Router Solicitation message processing.
NdpNeighborCacheEntry * ndpFindNeighborCacheEntry(NetInterface *interface, const Ipv6Addr *ipAddr)
Search the Neighbor cache for a given IPv6 address.
Definition: ndp_cache.c:103
#define timeCompare(t1, t2)
Definition: os_port.h:40
#define NDP_MAX_INITIAL_RTR_ADVERTISEMENTS
Definition: ndp.h:86
void ndpDumpRouterAdvMessage(const NdpRouterAdvMessage *message)
Dump Router Advertisement message for debugging purpose.
Definition: ndp.c:1906
error_t ipv6SelectSourceAddr(NetInterface **interface, const Ipv6Addr *destAddr, Ipv6Addr *srcAddr)
IPv6 source address selection.
Definition: ipv6_misc.c:879
#define NDP_DELAY_FIRST_PROBE_TIME
Definition: ndp.h:191
#define NDP_REACHABLE_TIME
Definition: ndp.h:177
#define ipv6GetLinkLocalAddrState(interface)
Definition: ipv6.h:139
systime_t osGetSystemTime(void)
Retrieve system time.
uint32_t time
const Ipv6Addr IPV6_LINK_LOCAL_ALL_ROUTERS_ADDR
Definition: ipv6.c:77
TCP/IP stack core.
void netBufferFree(NetBuffer *buffer)
Dispose a multi-part buffer.
Definition: net_mem.c:280
error_t ndpSendRouterAdv(NdpRouterAdvContext *context, uint16_t routerLifetime)
Send a Router Advertisement message.
Debugging facilities.
__start_packed struct @194 NdpRouterSolMessage
Router Solicitation message.
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:295
__start_packed struct @203 NdpMtuOption
MTU option.
const Ipv6Addr IPV6_LINK_LOCAL_ALL_NODES_ADDR
Definition: ipv6.c:73
Generic error code.
Definition: error.h:43
void * ndpGetOption(uint8_t *options, size_t length, uint8_t type)
Find a specified option in a NDP message.
Definition: ndp_misc.c:636
uint8_t message[]
Definition: chap.h:150
bool_t isRouter
A flag indicating whether the neighbor is a router or a host.
Definition: ndp.h:546
error_t netBufferSetLength(NetBuffer *buffer, size_t length)
Adjust the length of a multi-part buffer.
Definition: net_mem.c:318
Invalid parameter.
Definition: error.h:45
systime_t timestamp
Timestamp to manage retransmissions.
void ndpRouterAdvTick(NdpRouterAdvContext *context)
RA service timer handler.
error_t ndpRouterAdvInit(NdpRouterAdvContext *context, const NdpRouterAdvSettings *settings)
RA service initialization.
IPv4 and IPv6 common routines.
__start_packed struct @183 Ipv6Addr
IPv6 network address.
uint16_t routerLifetime
Definition: ndp.h:301
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:571
#define htons(value)
Definition: cpu_endian.h:390
NetInterface * interface
error_t ndpRouterAdvStop(NdpRouterAdvContext *context)
Stop RA service.
__start_packed struct @200 NdpLinkLayerAddrOption
Source/Target Link-Layer Address option.
#define NDP_HOP_LIMIT
Definition: ndp.h:197
#define TRUE
Definition: os_port.h:48
Neighbor and destination cache management.
bool_t running
This flag tells whether the RA service is running.
NdpRouterAdvContextInfo * contextList
RA service settings.
MacAddr macAddr
Link layer address associated with the IPv6 address.
Definition: ndp.h:545
NdpRouterAdvPrefixInfo * prefixList
Ipv6Addr ipAddr
Unicast IPv6 address.
Definition: ndp.h:544
systime_t timestamp
Timestamp to manage entry lifetime.
Definition: ndp.h:547
#define htonl(value)
Definition: cpu_endian.h:391
#define NDP_MAX_RA_DELAY_TIME
Definition: ndp.h:107
void * netBufferAt(const NetBuffer *buffer, size_t offset)
Returns a pointer to the data at the specified position.
Definition: net_mem.c:411
#define NDP_MIN_DELAY_BETWEEN_RAS
Definition: ndp.h:100
Helper functions for NDP (Neighbor Discovery Protocol)
NetBuffer * ipAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold an IP packet.
Definition: ip.c:596
NdpState state
Reachability state.
Definition: ndp.h:543
__start_packed struct @201 NdpPrefixInfoOption
Prefix Information option (PIO)
systime_t timeout
Timeout value.
Definition: ndp.h:548
error_t ndpRouterAdvStart(NdpRouterAdvContext *context)
Start RA service.
NetInterface * netGetDefaultInterface(void)
Get default network interface.
Definition: net.c:1495
RA service context.
#define Ipv6PseudoHeader
Definition: ipv6.h:40
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:86
#define NDP_MAX_INITIAL_RTR_ADVERT_INTERVAL
Definition: ndp.h:79
#define MIN(a, b)
Definition: os_port.h:60
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:53
An address assigned to an interface whose use is unrestricted.
Definition: ipv6.h:171
IP MIB module.
Helper functions for IPv6.
#define TRACE_INFO(...)
Definition: debug.h:86
IPv6 (Internet Protocol Version 6)
Success.
Definition: error.h:42
Neighbor cache entry.
Definition: ndp.h:541
__start_packed struct @204 NdpRouteInfoOption
Route Information option (RIO)
#define IPV6_DEFAULT_HOP_LIMIT
Definition: ipv6.h:57
int32_t netGetRandRange(int32_t min, int32_t max)
Get a random value in the specified range.
Definition: net.c:1554
__start_packed struct @199 NdpOption
Neighbor Discovery option general format.
void ndpRouterAdvLinkChangeEvent(NdpRouterAdvContext *context)
Callback function for link change event.
error_t
Error codes.
Definition: error.h:40
#define IP_MIB_INC_COUNTER32(name, value)
Definition: ip_mib_module.h:44
unsigned int uint_t
Definition: compiler_port.h:43
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
__start_packed struct @112 MacAddr
MAC address.
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:588
#define NDP_MAX_RTR_ADVERT_INTERVAL
Definition: ndp.h:72
ICMPv6 (Internet Control Message Protocol Version 6)
#define PRIuSIZE
Definition: compiler_port.h:72
#define NetInterface
Definition: net.h:34
NdpNeighborCacheEntry * ndpCreateNeighborCacheEntry(NetInterface *interface)
Create a new entry in the Neighbor cache.
Definition: ndp_cache.c:50
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:95
__start_packed struct @207 NdpContextOption
6LoWPAN Context option (6CO)
__start_packed struct @195 NdpRouterAdvMessage
Router Advertisement message.
systime_t ndpRouterAdvTickCounter
uint_t routerAdvCount
Router Advertisement message counter.
char_t * macAddrToString(const MacAddr *macAddr, char_t *str)
Convert a MAC address to a dash delimited string.
Definition: ethernet.c:1243
const Ipv6Addr IPV6_UNSPECIFIED_ADDR
Definition: ipv6.c:65
error_t ipv6LeaveMulticastGroup(NetInterface *interface, const Ipv6Addr *groupAddr)
Leave an IPv6 multicast group.
Definition: ipv6.c:2014
NDP (Neighbor Discovery Protocol)
OsMutex netMutex
Definition: net.c:70
NetInterface * nicGetLogicalInterface(NetInterface *interface)
Retrieve logical interface.
Definition: nic.c:60
#define NDP_RETRANS_TIMER
Definition: ndp.h:184
uint8_t length
Definition: dtls_misc.h:140
uint8_t n
#define Ipv6Header
Definition: ipv6.h:34
uint_t ndpSendQueuedPackets(NetInterface *interface, NdpNeighborCacheEntry *entry)
Send packets that are waiting for address resolution.
Definition: ndp_cache.c:290
error_t ipv6JoinMulticastGroup(NetInterface *interface, const Ipv6Addr *groupAddr)
Join an IPv6 multicast group.
Definition: ipv6.c:1904
Router advertisement service.
#define IPV6_DEFAULT_MTU
Definition: ipv6.h:107
#define FALSE
Definition: os_port.h:44
NdpRouterAdvRouteInfo * routeList
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
#define ipv6CompAddr(ipAddr1, ipAddr2)
Definition: ipv6.h:119
void ndpDumpRouterSolMessage(const NdpRouterSolMessage *message)
Dump Router Solicitation message for debugging purpose.
Definition: ndp.c:1892
systime_t timeout
Timeout value.
#define TRACE_DEBUG(...)
Definition: debug.h:98