Webserver+3d print

Dependents:   Nucleo

Committer:
Sergunb
Date:
Sat Feb 04 18:15:49 2017 +0000
Revision:
0:8918a71cdbe9
nothing else

Who changed what in which revision?

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