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