slaac.c
Go to the documentation of this file.
1 /**
2  * @file slaac.c
3  * @brief IPv6 Stateless Address Autoconfiguration
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2019 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  * Stateless Address Autoconfiguration is a facility to allow devices to
30  * configure themselves independently. Refer to the following RFCs for
31  * complete details:
32  * - RFC 4862: IPv6 Stateless Address Autoconfiguration
33  * - RFC 6106: IPv6 Router Advertisement Options for DNS Configuration
34  *
35  * @author Oryx Embedded SARL (www.oryx-embedded.com)
36  * @version 1.9.6
37  **/
38 
39 //Switch to the appropriate trace level
40 #define TRACE_LEVEL SLAAC_TRACE_LEVEL
41 
42 //Dependencies
43 #include "core/net.h"
44 #include "core/ethernet.h"
45 #include "ipv6/ipv6.h"
46 #include "ipv6/ipv6_misc.h"
47 #include "ipv6/slaac.h"
48 #include "ipv6/ndp.h"
49 #include "ipv6/ndp_misc.h"
50 #include "debug.h"
51 
52 //Check TCP/IP stack configuration
53 #if (IPV6_SUPPORT == ENABLED && SLAAC_SUPPORT == ENABLED)
54 
55 
56 /**
57  * @brief Initialize settings with default values
58  * @param[out] settings Structure that contains SLAAC settings
59  **/
60 
62 {
63  //Use default interface
64  settings->interface = netGetDefaultInterface();
65 
66  //Use the DNS servers specified by the RDNSS option
67  settings->manualDnsConfig = FALSE;
68  //Link state change event
69  settings->linkChangeEvent = NULL;
70  //Router Advertisement parsing callback
71  settings->parseRouterAdvCallback = NULL;
72 }
73 
74 
75 /**
76  * @brief SLAAC initialization
77  * @param[in] context Pointer to the SLAAC context
78  * @param[in] settings SLAAC specific settings
79  * @return Error code
80  **/
81 
82 error_t slaacInit(SlaacContext *context, const SlaacSettings *settings)
83 {
84  NetInterface *interface;
85 
86  //Debug message
87  TRACE_INFO("Initializing SLAAC...\r\n");
88 
89  //Ensure the parameters are valid
90  if(context == NULL || settings == NULL)
92 
93  //A valid pointer to the interface being configured is required
94  if(settings->interface == NULL)
96 
97  //Point to the underlying network interface
98  interface = settings->interface;
99 
100  //Clear the SLAAC context
101  memset(context, 0, sizeof(SlaacContext));
102  //Save user settings
103  context->settings = *settings;
104 
105  //SLAAC operation is currently suspended
106  context->running = FALSE;
107 
108  //Attach the SLAAC context to the network interface
109  interface->slaacContext = context;
110 
111  //Successful initialization
112  return NO_ERROR;
113 }
114 
115 
116 /**
117  * @brief Start SLAAC process
118  * @param[in] context Pointer to the SLAAC context
119  * @return Error code
120  **/
121 
123 {
124  NetInterface *interface;
125 
126  //Check parameter
127  if(context == NULL)
129 
130  //Debug message
131  TRACE_INFO("Starting SLAAC...\r\n");
132 
133  //Get exclusive access
135 
136  //Point to the underlying network interface
137  interface = context->settings.interface;
138 
139  //Clear the list of IPv6 addresses
140  ipv6FlushAddrList(interface);
141 
142  //Automatic DNS server configuration?
143  if(!context->settings.manualDnsConfig)
144  {
145  //Clear the list of DNS servers
146  ipv6FlushDnsServerList(interface);
147  }
148 
149  //Check if the link is up?
150  if(interface->linkState)
151  {
152  //A link-local address is formed by combining the well-known
153  //link-local prefix fe80::/10 with the interface identifier
155  }
156 
157  //Start SLAAC operation
158  context->running = TRUE;
159 
160  //Release exclusive access
162 
163  //Successful processing
164  return NO_ERROR;
165 }
166 
167 
168 /**
169  * @brief Stop SLAAC process
170  * @param[in] context Pointer to the SLAAC context
171  * @return Error code
172  **/
173 
175 {
176  //Check parameter
177  if(context == NULL)
179 
180  //Debug message
181  TRACE_INFO("Stopping SLAAC...\r\n");
182 
183  //Get exclusive access
185 
186  //Suspend SLAAC operation
187  context->running = FALSE;
188 
189  //Release exclusive access
191 
192  //Successful processing
193  return NO_ERROR;
194 }
195 
196 
197 /**
198  * @brief Callback function for link change event
199  * @param[in] context Pointer to the SLAAC context
200  **/
201 
203 {
204  NetInterface *interface;
205 
206  //Make sure the SLAAC service has been properly instantiated
207  if(context == NULL)
208  return;
209 
210  //Point to the underlying network interface
211  interface = context->settings.interface;
212 
213  //Check whether SLAAC is enabled
214  if(context->running)
215  {
216  //Automatic DNS server configuration?
217  if(!context->settings.manualDnsConfig)
218  {
219  //Clear the list of DNS servers
220  ipv6FlushDnsServerList(interface);
221  }
222 
223  //Link-up event?
224  if(interface->linkState)
225  {
226  //A link-local address is formed by combining the well-known
227  //link-local prefix fe80::/10 with the interface identifier
229  }
230  }
231 
232  //Any registered callback?
233  if(context->settings.linkChangeEvent != NULL)
234  {
235  //Release exclusive access
237  //Invoke user callback function
238  context->settings.linkChangeEvent(context, interface, interface->linkState);
239  //Get exclusive access
241  }
242 }
243 
244 
245 /**
246  * @brief Parse Router Advertisement message
247  * @param[in] context Pointer to the SLAAC context
248  * @param[in] message Pointer to the Router Advertisement message
249  * @param[in] length Length of the message, in bytes
250  **/
251 
254 {
255  uint_t i;
256  uint_t n;
257  NetInterface *interface;
258  NdpPrefixInfoOption *prefixInfoOption;
259  NdpRdnssOption *rdnssOption;
260 
261  //Point to the underlying network interface
262  interface = context->settings.interface;
263 
264  //Check whether SLAAC is enabled
265  if(!context->running)
266  return;
267 
268  //Make sure that a valid link-local address has been assigned to the interface
270  return;
271 
272  //Calculate the length of the Options field
273  length -= sizeof(NdpRouterAdvMessage);
274 
275  //This flag tracks changes in IPv6 configuration
276  context->configUpdated = FALSE;
277 
278  //Point to the beginning of the Options field
279  n = 0;
280 
281  //Parse Options field
282  while(1)
283  {
284  //Search the Options field for any Prefix Information options
285  prefixInfoOption = ndpGetOption(message->options + n,
287 
288  //No more option of the specified type?
289  if(prefixInfoOption == NULL)
290  break;
291 
292  //Parse the Prefix Information Option
293  slaacParsePrefixInfoOption(context, prefixInfoOption);
294 
295  //Retrieve the offset to the current position
296  n = (uint8_t *) prefixInfoOption - message->options;
297  //Jump to the next option
298  n += prefixInfoOption->length * 8;
299  }
300 
301  //Automatic DNS server configuration?
302  if(!context->settings.manualDnsConfig)
303  {
304  //Search for the Recursive DNS Server (RDNSS) option
305  rdnssOption = ndpGetOption(message->options, length,
307 
308  //RDNSS option found?
309  if(rdnssOption != NULL && rdnssOption->length >= 1)
310  {
311  //Retrieve the number of addresses
312  n = (rdnssOption->length - 1) / 2;
313 
314  //Loop through the list of DNS servers
315  for(i = 0; i < n && i < IPV6_DNS_SERVER_LIST_SIZE; i++)
316  {
317  //Record DNS server address
318  interface->ipv6Context.dnsServerList[i] = rdnssOption->address[i];
319  }
320  }
321  }
322 
323  //Any registered callback?
324  if(context->settings.parseRouterAdvCallback != NULL)
325  {
326  //Invoke user callback function
327  context->settings.parseRouterAdvCallback(context, message, length);
328  }
329 
330  //Check whether a new IPv6 address has been assigned to the interface
331  if(context->configUpdated)
332  {
333  //Dump current IPv6 configuration for debugging purpose
334  slaacDumpConfig(context);
335  }
336 }
337 
338 
339 /**
340  * @brief Parse Prefix Information Option
341  * @param[in] context Pointer to the SLAAC context
342  * @param[in] option Pointer to the Prefix Information option
343  **/
344 
346  NdpPrefixInfoOption *option)
347 {
348  uint_t i;
349  bool_t found;
350  systime_t time;
353  systime_t remainingLifetime;
354  NetInterface *interface;
355  NetInterface *logicalInterface;
356  Ipv6AddrEntry *entry;
357  Ipv6Addr addr;
358 
359  //Make sure the Prefix Information option is valid
360  if(option == NULL || option->length != 4)
361  return;
362 
363  //If the Autonomous flag is not set, silently ignore the Prefix
364  //Information option
365  if(!option->a)
366  return;
367 
368  //If the prefix is the link-local prefix, silently ignore the
369  //Prefix Information option
370  if(ipv6CompPrefix(&option->prefix, &IPV6_LINK_LOCAL_ADDR_PREFIX, 10))
371  return;
372 
373  //Check whether the valid lifetime is zero
374  if(ntohl(option->validLifetime) == 0)
375  return;
376 
377  //If the preferred lifetime is greater than the valid lifetime,
378  //silently ignore the Prefix Information option
379  if(ntohl(option->preferredLifetime) > ntohl(option->validLifetime))
380  return;
381 
382  //If the sum of the prefix length and interface identifier length does
383  //not equal 128 bits, the Prefix Information option must be ignored
384  if(option->prefixLength != 64)
385  return;
386 
387  //Get current time
388  time = osGetSystemTime();
389 
390  //Point to the underlying network interface
391  interface = context->settings.interface;
392 
393  //Point to the logical interface
394  logicalInterface = nicGetLogicalInterface(interface);
395 
396  //Form an address by combining the advertised prefix with the interface
397  //identifier
398  addr.w[0] = option->prefix.w[0];
399  addr.w[1] = option->prefix.w[1];
400  addr.w[2] = option->prefix.w[2];
401  addr.w[3] = option->prefix.w[3];
402  addr.w[4] = logicalInterface->eui64.w[0];
403  addr.w[5] = logicalInterface->eui64.w[1];
404  addr.w[6] = logicalInterface->eui64.w[2];
405  addr.w[7] = logicalInterface->eui64.w[3];
406 
407  //Convert Valid Lifetime to host byte order
408  validLifetime = ntohl(option->validLifetime);
409 
410  //Check the valid lifetime
412  {
413  //The length of time in seconds that the prefix is valid for the
414  //purpose of on-link determination
415  if(validLifetime < (MAX_DELAY / 1000))
416  validLifetime *= 1000;
417  else
419  }
420  else
421  {
422  //A value of all one bits (0xffffffff) represents infinity
424  }
425 
426  //Convert Preferred Lifetime to host byte order
427  preferredLifetime = ntohl(option->preferredLifetime);
428 
429  //Check the preferred lifetime
431  {
432  //The length of time in seconds that addresses generated from the
433  //prefix via stateless address autoconfiguration remain preferred
434  if(preferredLifetime < (MAX_DELAY / 1000))
435  preferredLifetime *= 1000;
436  else
438  }
439  else
440  {
441  //A value of all one bits (0xffffffff) represents infinity
443  }
444 
445  //This flag will be set if the advertised prefix matches an address
446  //assigned to the interface
447  found = FALSE;
448 
449  //Loop through the list of IPv6 addresses
450  for(i = 1; i < IPV6_ADDR_LIST_SIZE; i++)
451  {
452  //Point to the current entry
453  entry = &interface->ipv6Context.addrList[i];
454 
455  //Check whether the advertised prefix is equal to the prefix of an
456  //address configured by stateless autoconfiguration in the list
457  if(ipv6CompPrefix(&entry->addr, &option->prefix, option->prefixLength))
458  {
459  //Valid address?
460  if(entry->state == IPV6_ADDR_STATE_PREFERRED ||
462  {
463  //Set flag
464  found = TRUE;
465 
466  //The preferred lifetime of the address is reset to the Preferred
467  //Lifetime in the received advertisement
469 
470  //Compute the remaining time to the valid lifetime expiration
471  //of the previously autoconfigured address
472  if(timeCompare(time, entry->timestamp + entry->validLifetime) < 0)
473  remainingLifetime = entry->timestamp + entry->validLifetime - time;
474  else
475  remainingLifetime = 0;
476 
477  //The specific action to perform for the valid lifetime of the
478  //address depends on the Valid Lifetime in the received Router
479  //Advertisement and the remaining time
481  validLifetime > remainingLifetime)
482  {
483  //If the received Valid Lifetime is greater than 2 hours or
484  //greater than remaining lifetime, set the valid lifetime of
485  //the corresponding address to the advertised Valid Lifetime
486  entry->validLifetime = validLifetime;
487 
488  //Save current time
489  entry->timestamp = time;
490  //Update the state of the IPv6 address
492  }
493  else if(remainingLifetime <= SLAAC_LIFETIME_2_HOURS)
494  {
495  //If remaining lifetime is less than or equal to 2 hours, ignore
496  //the Prefix Information option with regards to the valid lifetime
497  }
498  else
499  {
500  //Otherwise, reset the valid lifetime of the corresponding
501  //address to 2 hours
503 
504  //Save current time
505  entry->timestamp = time;
506  //Update the state of the IPv6 address
508  }
509  }
510  //Tentative address?
511  else if(entry->state == IPV6_ADDR_STATE_TENTATIVE)
512  {
513  //Do not update the preferred and valid lifetimes of the address
514  //when Duplicate Address Detection is being performed
515  found = TRUE;
516  }
517  }
518  }
519 
520  //The IPv6 address is not yet in the list?
521  if(!found)
522  {
523  //Loop through the list of IPv6 addresses
524  for(i = 1; i < IPV6_ADDR_LIST_SIZE; i++)
525  {
526  //Point to the current entry
527  entry = &interface->ipv6Context.addrList[i];
528 
529  //Check the state of the IPv6 address
530  if(entry->state == IPV6_ADDR_STATE_INVALID)
531  {
532  //If an address is formed successfully and the address is not yet
533  //in the list, the host adds it to the list of addresses assigned
534  //to the interface, initializing its preferred and valid lifetime
535  //values from the Prefix Information option
536  if(interface->ndpContext.dupAddrDetectTransmits > 0)
537  {
538  //Use the IPv6 address as a tentative address
541  }
542  else
543  {
544  //The use of the IPv6 address is now unrestricted
547  }
548 
549  //A new IPv6 address has just been assigned to the interface
550  context->configUpdated = TRUE;
551  //We are done
552  break;
553  }
554  }
555  }
556 }
557 
558 
559 /**
560  * @brief Generate a link-local address
561  * @param[in] context Pointer to the SLAAC context
562  * @return Error code
563  **/
564 
566 {
567  error_t error;
568  NetInterface *interface;
569  NetInterface *logicalInterface;
570  Ipv6Addr addr;
571 
572  //Point to the underlying network interface
573  interface = context->settings.interface;
574 
575  //Point to the logical interface
576  logicalInterface = nicGetLogicalInterface(interface);
577 
578  //Check whether a link-local address has been manually assigned
579  if(interface->ipv6Context.addrList[0].state != IPV6_ADDR_STATE_INVALID &&
580  interface->ipv6Context.addrList[0].permanent)
581  {
582  //Keep using the current link-local address
583  error = NO_ERROR;
584  }
585  else
586  {
587  //A link-local address is formed by combining the well-known
588  //link-local prefix fe80::/10 with the interface identifier
589  ipv6GenerateLinkLocalAddr(&logicalInterface->eui64, &addr);
590 
591  //Check whether Duplicate Address Detection should be performed
592  if(interface->ndpContext.dupAddrDetectTransmits > 0)
593  {
594  //Use the link-local address as a tentative address
595  error = ipv6SetAddr(interface, 0, &addr, IPV6_ADDR_STATE_TENTATIVE,
597  }
598  else
599  {
600  //The use of the link-local address is now unrestricted
601  error = ipv6SetAddr(interface, 0, &addr, IPV6_ADDR_STATE_PREFERRED,
603  }
604  }
605 
606  //Return status code
607  return error;
608 }
609 
610 
611 /**
612  * @brief Dump IPv6 configuration for debugging purpose
613  * @param[in] context Pointer to the SLAAC context
614  **/
615 
617 {
618 #if (SLAAC_TRACE_LEVEL >= TRACE_LEVEL_INFO)
619  uint_t i;
620  NetInterface *interface;
621  Ipv6Context *ipv6Context;
622 
623  //Point to the underlying network interface
624  interface = context->settings.interface;
625  //Point to the IPv6 context
626  ipv6Context = &interface->ipv6Context;
627 
628  //Debug message
629  TRACE_INFO("\r\n");
630  TRACE_INFO("SLAAC configuration:\r\n");
631 
632  //Link-local address
633  TRACE_INFO(" Link-local Address = %s\r\n",
634  ipv6AddrToString(&ipv6Context->addrList[0].addr, NULL));
635 
636  //Global addresses
637  for(i = 1; i < IPV6_ADDR_LIST_SIZE; i++)
638  {
639  TRACE_INFO(" Global Address %u = %s\r\n", i,
640  ipv6AddrToString(&ipv6Context->addrList[i].addr, NULL));
641  }
642 
643  //IPv6 prefixes
644  for(i = 0; i < IPV6_PREFIX_LIST_SIZE; i++)
645  {
646  TRACE_INFO(" Prefix %u = %s/%" PRIu8 "\r\n", i + 1,
647  ipv6AddrToString(&ipv6Context->prefixList[i].prefix, NULL),
648  ipv6Context->prefixList[i].prefixLen);
649  }
650 
651  //Default routers
652  for(i = 0; i < IPV6_ROUTER_LIST_SIZE; i++)
653  {
654  TRACE_INFO(" Default Router %u = %s\r\n", i + 1,
655  ipv6AddrToString(&ipv6Context->routerList[i].addr, NULL));
656  }
657 
658  //DNS servers
659  for(i = 0; i < IPV6_DNS_SERVER_LIST_SIZE; i++)
660  {
661  TRACE_INFO(" DNS Server %u = %s\r\n", i + 1,
662  ipv6AddrToString(&ipv6Context->dnsServerList[i], NULL));
663  }
664 
665  //Maximum transmit unit
666  TRACE_INFO(" MTU = %" PRIuSIZE "\r\n", ipv6Context->linkMtu);
667  TRACE_INFO("\r\n");
668 #endif
669 }
670 
671 #endif
@ IPV6_ADDR_STATE_TENTATIVE
An address whose uniqueness on a link is being verified.
Definition: ipv6.h:172
char_t * ipv6AddrToString(const Ipv6Addr *ipAddr, char_t *str)
Convert a binary IPv6 address to a string representation.
Definition: ipv6.c:2254
IPv6 (Internet Protocol Version 6)
uint8_t length
Definition: dtls_misc.h:149
int bool_t
Definition: compiler_port.h:49
#define SLAAC_LIFETIME_2_HOURS
Definition: slaac.h:46
Helper functions for NDP (Neighbor Discovery Protocol)
#define TRUE
Definition: os_port.h:50
uint32_t preferredLifetime
SlaacLinkChangeCallback linkChangeEvent
Link state change event.
Definition: slaac.h:82
Ipv6Addr addr
IPv6 address.
Definition: ipv6.h:401
systime_t preferredLifetime
Preferred lifetime.
Definition: ipv6.h:405
void slaacDumpConfig(SlaacContext *context)
Dump IPv6 configuration for debugging purpose.
Definition: slaac.c:616
void ipv6FlushAddrList(NetInterface *interface)
Flush the list of IPv6 addresses.
Definition: ipv6_misc.c:644
#define NDP_INFINITE_LIFETIME
Definition: ndp.h:202
#define timeCompare(t1, t2)
Definition: os_port.h:42
IPv6 Stateless Address Autoconfiguration.
SlaacParseRouterAdvCallback parseRouterAdvCallback
Router Advertisement parsing callback.
Definition: slaac.h:83
IPv6 context.
Definition: ipv6.h:462
__start_packed struct @201 NdpRdnssOption
Recursive DNS Server option (RDNSS)
@ IPV6_ADDR_STATE_INVALID
An address that is not assigned to any interface.
Definition: ipv6.h:171
Ethernet.
@ NDP_OPT_RECURSIVE_DNS_SERVER
Definition: ndp.h:222
#define FALSE
Definition: os_port.h:46
__start_packed struct @197 NdpPrefixInfoOption
Prefix Information option (PIO)
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
void ipv6FlushDnsServerList(NetInterface *interface)
Flush the list of DNS servers.
Definition: ipv6_misc.c:739
#define SlaacContext
Definition: slaac.h:50
error_t
Error codes.
Definition: error.h:42
#define NetInterface
Definition: net.h:36
NetInterface * netGetDefaultInterface(void)
Get default network interface.
Definition: net.c:1782
Helper functions for IPv6.
void slaacGetDefaultSettings(SlaacSettings *settings)
Initialize settings with default values.
Definition: slaac.c:61
OsMutex netMutex
Definition: net.c:75
__start_packed struct @179 Ipv6Addr
IPv6 network address.
#define IPV6_DNS_SERVER_LIST_SIZE
Definition: ipv6.h:94
void slaacParseRouterAdv(SlaacContext *context, NdpRouterAdvMessage *message, size_t length)
Parse Router Advertisement message.
Definition: slaac.c:252
#define TRACE_INFO(...)
Definition: debug.h:94
bool_t manualDnsConfig
Force manual DNS configuration.
Definition: slaac.h:81
error_t slaacGenerateLinkLocalAddr(SlaacContext *context)
Generate a link-local address.
Definition: slaac.c:565
NDP (Neighbor Discovery Protocol)
void slaacParsePrefixInfoOption(SlaacContext *context, NdpPrefixInfoOption *option)
Parse Prefix Information Option.
Definition: slaac.c:345
error_t ipv6SetAddr(NetInterface *interface, uint_t index, const Ipv6Addr *addr, Ipv6AddrState state, systime_t validLifetime, systime_t preferredLifetime, bool_t permanent)
Set IPv6 address and address state.
Definition: ipv6_misc.c:95
error_t slaacInit(SlaacContext *context, const SlaacSettings *settings)
SLAAC initialization.
Definition: slaac.c:82
__start_packed struct @191 NdpRouterAdvMessage
Router Advertisement message.
uint32_t time
void slaacLinkChangeEvent(SlaacContext *context)
Callback function for link change event.
Definition: slaac.c:202
IPv6 address entry.
Definition: ipv6.h:399
error_t slaacStart(SlaacContext *context)
Start SLAAC process.
Definition: slaac.c:122
uint8_t n
#define IPV6_ROUTER_LIST_SIZE
Definition: ipv6.h:87
#define IPV6_ADDR_LIST_SIZE
Definition: ipv6.h:66
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
void * ndpGetOption(uint8_t *options, size_t length, uint8_t type)
Find a specified option in a NDP message.
Definition: ndp_misc.c:645
void ipv6GenerateLinkLocalAddr(const Eui64 *interfaceId, Ipv6Addr *ipAddr)
Generate a IPv6 link-local address from an interface identifier.
Definition: ipv6_misc.c:1455
@ NDP_OPT_PREFIX_INFORMATION
Definition: ndp.h:218
uint8_t message[]
Definition: chap.h:152
bool_t ipv6CompPrefix(const Ipv6Addr *ipAddr1, const Ipv6Addr *ipAddr2, size_t length)
Compare IPv6 address prefixes.
Definition: ipv6_misc.c:1208
systime_t validLifetime
Valid lifetime.
Definition: ipv6.h:404
uint32_t validLifetime
Ipv4Addr addr
Definition: nbns_common.h:121
#define MAX_DELAY
Definition: os_port.h:76
@ IPV6_ADDR_STATE_PREFERRED
An address assigned to an interface whose use is unrestricted.
Definition: ipv6.h:173
Ipv6AddrState state
IPv6 address state.
Definition: ipv6.h:402
#define IPV6_PREFIX_LIST_SIZE
Definition: ipv6.h:80
#define PRIuSIZE
Definition: compiler_port.h:78
unsigned int uint_t
Definition: compiler_port.h:45
NetInterface * interface
Network interface to configure.
Definition: slaac.h:80
TCP/IP stack core.
NetInterface * nicGetLogicalInterface(NetInterface *interface)
Retrieve logical interface.
Definition: nic.c:52
@ IPV6_ADDR_STATE_DEPRECATED
An address assigned to an interface whose use is discouraged.
Definition: ipv6.h:174
error_t slaacStop(SlaacContext *context)
Stop SLAAC process.
Definition: slaac.c:174
const Ipv6Addr IPV6_LINK_LOCAL_ADDR_PREFIX
Definition: ipv6.c:83
#define ipv6GetLinkLocalAddrState(interface)
Definition: ipv6.h:141
uint32_t systime_t
Definition: compiler_port.h:46
#define ntohl(value)
Definition: cpu_endian.h:399
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
#define INFINITE_DELAY
Definition: os_port.h:74
systime_t timestamp
Timestamp to manage entry lifetime.
Definition: ipv6.h:407
systime_t osGetSystemTime(void)
Retrieve system time.
SLAAC settings.
Definition: slaac.h:78