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 ndp.c
Sergunb 0:8918a71cdbe9 3 * @brief NDP (Neighbor Discovery Protocol)
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 * The Neighbor Discovery Protocol is responsible for address autoconfiguration
Sergunb 0:8918a71cdbe9 28 * of nodes, discovery of the link-layer addresses of other nodes, duplicate
Sergunb 0:8918a71cdbe9 29 * address detection, finding available routers and address prefix discovery.
Sergunb 0:8918a71cdbe9 30 * Refer to RFC 4861 for more details
Sergunb 0:8918a71cdbe9 31 *
Sergunb 0:8918a71cdbe9 32 * @author Oryx Embedded SARL (www.oryx-embedded.com)
Sergunb 0:8918a71cdbe9 33 * @version 1.7.6
Sergunb 0:8918a71cdbe9 34 **/
Sergunb 0:8918a71cdbe9 35
Sergunb 0:8918a71cdbe9 36 //Switch to the appropriate trace level
Sergunb 0:8918a71cdbe9 37 #define TRACE_LEVEL NDP_TRACE_LEVEL
Sergunb 0:8918a71cdbe9 38
Sergunb 0:8918a71cdbe9 39 //Dependencies
Sergunb 0:8918a71cdbe9 40 #include <limits.h>
Sergunb 0:8918a71cdbe9 41 #include <string.h>
Sergunb 0:8918a71cdbe9 42 #include "core/net.h"
Sergunb 0:8918a71cdbe9 43 #include "ipv6/ipv6.h"
Sergunb 0:8918a71cdbe9 44 #include "ipv6/ipv6_misc.h"
Sergunb 0:8918a71cdbe9 45 #include "ipv6/icmpv6.h"
Sergunb 0:8918a71cdbe9 46 #include "ipv6/ndp.h"
Sergunb 0:8918a71cdbe9 47 #include "ipv6/ndp_cache.h"
Sergunb 0:8918a71cdbe9 48 #include "ipv6/ndp_misc.h"
Sergunb 0:8918a71cdbe9 49 #include "ipv6/slaac.h"
Sergunb 0:8918a71cdbe9 50 #include "debug.h"
Sergunb 0:8918a71cdbe9 51
Sergunb 0:8918a71cdbe9 52 //Check TCP/IP stack configuration
Sergunb 0:8918a71cdbe9 53 #if (IPV6_SUPPORT == ENABLED && NDP_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 54
Sergunb 0:8918a71cdbe9 55 //Tick counter to handle periodic operations
Sergunb 0:8918a71cdbe9 56 systime_t ndpTickCounter;
Sergunb 0:8918a71cdbe9 57
Sergunb 0:8918a71cdbe9 58
Sergunb 0:8918a71cdbe9 59 /**
Sergunb 0:8918a71cdbe9 60 * @brief Neighbor cache initialization
Sergunb 0:8918a71cdbe9 61 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 62 * @return Error code
Sergunb 0:8918a71cdbe9 63 **/
Sergunb 0:8918a71cdbe9 64
Sergunb 0:8918a71cdbe9 65 error_t ndpInit(NetInterface *interface)
Sergunb 0:8918a71cdbe9 66 {
Sergunb 0:8918a71cdbe9 67 NdpContext *context;
Sergunb 0:8918a71cdbe9 68
Sergunb 0:8918a71cdbe9 69 //Point to the NDP context
Sergunb 0:8918a71cdbe9 70 context = &interface->ndpContext;
Sergunb 0:8918a71cdbe9 71
Sergunb 0:8918a71cdbe9 72 //Clear the NDP context
Sergunb 0:8918a71cdbe9 73 memset(context, 0, sizeof(NdpContext));
Sergunb 0:8918a71cdbe9 74
Sergunb 0:8918a71cdbe9 75 //Initialize interface specific variables
Sergunb 0:8918a71cdbe9 76 context->reachableTime = NDP_REACHABLE_TIME;
Sergunb 0:8918a71cdbe9 77 context->retransTimer = NDP_RETRANS_TIMER;
Sergunb 0:8918a71cdbe9 78 context->dupAddrDetectTransmits = NDP_DUP_ADDR_DETECT_TRANSMITS;
Sergunb 0:8918a71cdbe9 79 context->minRtrSolicitationDelay = NDP_MIN_RTR_SOLICITATION_DELAY;
Sergunb 0:8918a71cdbe9 80 context->maxRtrSolicitationDelay = NDP_MAX_RTR_SOLICITATION_DELAY;
Sergunb 0:8918a71cdbe9 81 context->rtrSolicitationInterval = NDP_RTR_SOLICITATION_INTERVAL;
Sergunb 0:8918a71cdbe9 82 context->maxRtrSolicitations = NDP_MAX_RTR_SOLICITATIONS;
Sergunb 0:8918a71cdbe9 83
Sergunb 0:8918a71cdbe9 84 //Successful initialization
Sergunb 0:8918a71cdbe9 85 return NO_ERROR;
Sergunb 0:8918a71cdbe9 86 }
Sergunb 0:8918a71cdbe9 87
Sergunb 0:8918a71cdbe9 88
Sergunb 0:8918a71cdbe9 89 /**
Sergunb 0:8918a71cdbe9 90 * @brief Address resolution using Neighbor Discovery protocol
Sergunb 0:8918a71cdbe9 91 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 92 * @param[in] ipAddr IPv6 address
Sergunb 0:8918a71cdbe9 93 * @param[in] macAddr Physical address matching the specified IPv6 address
Sergunb 0:8918a71cdbe9 94 * @return Error code
Sergunb 0:8918a71cdbe9 95 **/
Sergunb 0:8918a71cdbe9 96
Sergunb 0:8918a71cdbe9 97 error_t ndpResolve(NetInterface *interface, const Ipv6Addr *ipAddr, MacAddr *macAddr)
Sergunb 0:8918a71cdbe9 98 {
Sergunb 0:8918a71cdbe9 99 error_t error;
Sergunb 0:8918a71cdbe9 100 NdpNeighborCacheEntry *entry;
Sergunb 0:8918a71cdbe9 101
Sergunb 0:8918a71cdbe9 102 //Search the ndpCacheMutex cache for the specified IPv6 address
Sergunb 0:8918a71cdbe9 103 entry = ndpFindNeighborCacheEntry(interface, ipAddr);
Sergunb 0:8918a71cdbe9 104
Sergunb 0:8918a71cdbe9 105 //Check whether a matching entry has been found
Sergunb 0:8918a71cdbe9 106 if(entry != NULL)
Sergunb 0:8918a71cdbe9 107 {
Sergunb 0:8918a71cdbe9 108 //Check the state of the Neighbor cache entry
Sergunb 0:8918a71cdbe9 109 if(entry->state == NDP_STATE_INCOMPLETE)
Sergunb 0:8918a71cdbe9 110 {
Sergunb 0:8918a71cdbe9 111 //The address resolution is already in progress
Sergunb 0:8918a71cdbe9 112 error = ERROR_IN_PROGRESS;
Sergunb 0:8918a71cdbe9 113 }
Sergunb 0:8918a71cdbe9 114 else if(entry->state == NDP_STATE_STALE)
Sergunb 0:8918a71cdbe9 115 {
Sergunb 0:8918a71cdbe9 116 //Copy the MAC address associated with the specified IPv6 address
Sergunb 0:8918a71cdbe9 117 *macAddr = entry->macAddr;
Sergunb 0:8918a71cdbe9 118
Sergunb 0:8918a71cdbe9 119 //Start delay timer
Sergunb 0:8918a71cdbe9 120 entry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 121 //Delay before sending the first probe
Sergunb 0:8918a71cdbe9 122 entry->timeout = NDP_DELAY_FIRST_PROBE_TIME;
Sergunb 0:8918a71cdbe9 123 //Switch to the DELAY state
Sergunb 0:8918a71cdbe9 124 entry->state = NDP_STATE_DELAY;
Sergunb 0:8918a71cdbe9 125
Sergunb 0:8918a71cdbe9 126 //Successful address resolution
Sergunb 0:8918a71cdbe9 127 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 128 }
Sergunb 0:8918a71cdbe9 129 else
Sergunb 0:8918a71cdbe9 130 {
Sergunb 0:8918a71cdbe9 131 //Copy the MAC address associated with the specified IPv6 address
Sergunb 0:8918a71cdbe9 132 *macAddr = entry->macAddr;
Sergunb 0:8918a71cdbe9 133
Sergunb 0:8918a71cdbe9 134 //Successful address resolution
Sergunb 0:8918a71cdbe9 135 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 136 }
Sergunb 0:8918a71cdbe9 137 }
Sergunb 0:8918a71cdbe9 138 else
Sergunb 0:8918a71cdbe9 139 {
Sergunb 0:8918a71cdbe9 140 //If no entry exists, then create a new one
Sergunb 0:8918a71cdbe9 141 entry = ndpCreateNeighborCacheEntry(interface);
Sergunb 0:8918a71cdbe9 142
Sergunb 0:8918a71cdbe9 143 //Neighbor Cache entry successfully created?
Sergunb 0:8918a71cdbe9 144 if(entry != NULL)
Sergunb 0:8918a71cdbe9 145 {
Sergunb 0:8918a71cdbe9 146 //Record the IPv6 address whose MAC address is unknown
Sergunb 0:8918a71cdbe9 147 entry->ipAddr = *ipAddr;
Sergunb 0:8918a71cdbe9 148
Sergunb 0:8918a71cdbe9 149 //Reset retransmission counter
Sergunb 0:8918a71cdbe9 150 entry->retransmitCount = 0;
Sergunb 0:8918a71cdbe9 151 //No packet are pending in the transmit queue
Sergunb 0:8918a71cdbe9 152 entry->queueSize = 0;
Sergunb 0:8918a71cdbe9 153
Sergunb 0:8918a71cdbe9 154 //Send a multicast Neighbor Solicitation message
Sergunb 0:8918a71cdbe9 155 ndpSendNeighborSol(interface, ipAddr, TRUE);
Sergunb 0:8918a71cdbe9 156
Sergunb 0:8918a71cdbe9 157 //Save the time at which the message was sent
Sergunb 0:8918a71cdbe9 158 entry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 159 //Set timeout value
Sergunb 0:8918a71cdbe9 160 entry->timeout = interface->ndpContext.retransTimer;
Sergunb 0:8918a71cdbe9 161 //Enter INCOMPLETE state
Sergunb 0:8918a71cdbe9 162 entry->state = NDP_STATE_INCOMPLETE;
Sergunb 0:8918a71cdbe9 163
Sergunb 0:8918a71cdbe9 164 //The address resolution is in progress
Sergunb 0:8918a71cdbe9 165 error = ERROR_IN_PROGRESS;
Sergunb 0:8918a71cdbe9 166 }
Sergunb 0:8918a71cdbe9 167 else
Sergunb 0:8918a71cdbe9 168 {
Sergunb 0:8918a71cdbe9 169 //Failed to create Neighbor Cache entry...
Sergunb 0:8918a71cdbe9 170 error = ERROR_OUT_OF_RESOURCES;
Sergunb 0:8918a71cdbe9 171 }
Sergunb 0:8918a71cdbe9 172 }
Sergunb 0:8918a71cdbe9 173
Sergunb 0:8918a71cdbe9 174 //Return status code
Sergunb 0:8918a71cdbe9 175 return error;
Sergunb 0:8918a71cdbe9 176 }
Sergunb 0:8918a71cdbe9 177
Sergunb 0:8918a71cdbe9 178
Sergunb 0:8918a71cdbe9 179 /**
Sergunb 0:8918a71cdbe9 180 * @brief Enqueue an IPv6 packet waiting for address resolution
Sergunb 0:8918a71cdbe9 181 * @param[in] srcInterface Interface from which the packet has been received
Sergunb 0:8918a71cdbe9 182 * @param[in] destInterface Interface on which the packet should be sent
Sergunb 0:8918a71cdbe9 183 * @param[in] ipAddr IPv6 address of the destination host
Sergunb 0:8918a71cdbe9 184 * @param[in] buffer Multi-part buffer containing the packet to be enqueued
Sergunb 0:8918a71cdbe9 185 * @param[in] offset Offset to the first byte of the packet
Sergunb 0:8918a71cdbe9 186 * @return Error code
Sergunb 0:8918a71cdbe9 187 **/
Sergunb 0:8918a71cdbe9 188
Sergunb 0:8918a71cdbe9 189 error_t ndpEnqueuePacket(NetInterface *srcInterface, NetInterface *destInterface,
Sergunb 0:8918a71cdbe9 190 const Ipv6Addr *ipAddr, NetBuffer *buffer, size_t offset)
Sergunb 0:8918a71cdbe9 191 {
Sergunb 0:8918a71cdbe9 192 error_t error;
Sergunb 0:8918a71cdbe9 193 uint_t i;
Sergunb 0:8918a71cdbe9 194 size_t length;
Sergunb 0:8918a71cdbe9 195 NdpNeighborCacheEntry *entry;
Sergunb 0:8918a71cdbe9 196
Sergunb 0:8918a71cdbe9 197 //Retrieve the length of the multi-part buffer
Sergunb 0:8918a71cdbe9 198 length = netBufferGetLength(buffer);
Sergunb 0:8918a71cdbe9 199
Sergunb 0:8918a71cdbe9 200 //Search the Neighbor cache for the specified IPv6 address
Sergunb 0:8918a71cdbe9 201 entry = ndpFindNeighborCacheEntry(destInterface, ipAddr);
Sergunb 0:8918a71cdbe9 202
Sergunb 0:8918a71cdbe9 203 //Check whether a matching entry exists
Sergunb 0:8918a71cdbe9 204 if(entry != NULL)
Sergunb 0:8918a71cdbe9 205 {
Sergunb 0:8918a71cdbe9 206 //Check current state
Sergunb 0:8918a71cdbe9 207 if(entry->state == NDP_STATE_INCOMPLETE)
Sergunb 0:8918a71cdbe9 208 {
Sergunb 0:8918a71cdbe9 209 //Check whether the packet queue is full
Sergunb 0:8918a71cdbe9 210 if(entry->queueSize >= NDP_MAX_PENDING_PACKETS)
Sergunb 0:8918a71cdbe9 211 {
Sergunb 0:8918a71cdbe9 212 //When the queue overflows, the new arrival should replace the oldest entry
Sergunb 0:8918a71cdbe9 213 netBufferFree(entry->queue[0].buffer);
Sergunb 0:8918a71cdbe9 214
Sergunb 0:8918a71cdbe9 215 //Make room for the new packet
Sergunb 0:8918a71cdbe9 216 for(i = 1; i < NDP_MAX_PENDING_PACKETS; i++)
Sergunb 0:8918a71cdbe9 217 entry->queue[i - 1] = entry->queue[i];
Sergunb 0:8918a71cdbe9 218
Sergunb 0:8918a71cdbe9 219 //Adjust the number of pending packets
Sergunb 0:8918a71cdbe9 220 entry->queueSize--;
Sergunb 0:8918a71cdbe9 221 }
Sergunb 0:8918a71cdbe9 222
Sergunb 0:8918a71cdbe9 223 //Index of the entry to be filled in
Sergunb 0:8918a71cdbe9 224 i = entry->queueSize;
Sergunb 0:8918a71cdbe9 225 //Allocate a memory buffer to store the packet
Sergunb 0:8918a71cdbe9 226 entry->queue[i].buffer = netBufferAlloc(length);
Sergunb 0:8918a71cdbe9 227
Sergunb 0:8918a71cdbe9 228 //Successful memory allocation?
Sergunb 0:8918a71cdbe9 229 if(entry->queue[i].buffer != NULL)
Sergunb 0:8918a71cdbe9 230 {
Sergunb 0:8918a71cdbe9 231 //If the IPv6 packet has been forwarded, record the network
Sergunb 0:8918a71cdbe9 232 //interface from which the packet has been received
Sergunb 0:8918a71cdbe9 233 entry->queue[i].srcInterface = srcInterface;
Sergunb 0:8918a71cdbe9 234
Sergunb 0:8918a71cdbe9 235 //Copy the contents of the IPv6 packet
Sergunb 0:8918a71cdbe9 236 netBufferCopy(entry->queue[i].buffer, 0, buffer, 0, length);
Sergunb 0:8918a71cdbe9 237 //Offset to the first byte of the IPv6 header
Sergunb 0:8918a71cdbe9 238 entry->queue[i].offset = offset;
Sergunb 0:8918a71cdbe9 239
Sergunb 0:8918a71cdbe9 240 //Increment the number of queued packets
Sergunb 0:8918a71cdbe9 241 entry->queueSize++;
Sergunb 0:8918a71cdbe9 242 //The packet was successfully enqueued
Sergunb 0:8918a71cdbe9 243 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 244 }
Sergunb 0:8918a71cdbe9 245 else
Sergunb 0:8918a71cdbe9 246 {
Sergunb 0:8918a71cdbe9 247 //Failed to allocate memory
Sergunb 0:8918a71cdbe9 248 error = ERROR_OUT_OF_MEMORY;
Sergunb 0:8918a71cdbe9 249 }
Sergunb 0:8918a71cdbe9 250 }
Sergunb 0:8918a71cdbe9 251 else
Sergunb 0:8918a71cdbe9 252 {
Sergunb 0:8918a71cdbe9 253 //The address is already resolved
Sergunb 0:8918a71cdbe9 254 error = ERROR_UNEXPECTED_STATE;
Sergunb 0:8918a71cdbe9 255 }
Sergunb 0:8918a71cdbe9 256 }
Sergunb 0:8918a71cdbe9 257 else
Sergunb 0:8918a71cdbe9 258 {
Sergunb 0:8918a71cdbe9 259 //No matching entry in Neighbor Cache
Sergunb 0:8918a71cdbe9 260 error = ERROR_NOT_FOUND;
Sergunb 0:8918a71cdbe9 261 }
Sergunb 0:8918a71cdbe9 262
Sergunb 0:8918a71cdbe9 263 //Return status code
Sergunb 0:8918a71cdbe9 264 return error;
Sergunb 0:8918a71cdbe9 265 }
Sergunb 0:8918a71cdbe9 266
Sergunb 0:8918a71cdbe9 267
Sergunb 0:8918a71cdbe9 268 /**
Sergunb 0:8918a71cdbe9 269 * @brief NDP timer handler
Sergunb 0:8918a71cdbe9 270 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 271 **/
Sergunb 0:8918a71cdbe9 272
Sergunb 0:8918a71cdbe9 273 void ndpTick(NetInterface *interface)
Sergunb 0:8918a71cdbe9 274 {
Sergunb 0:8918a71cdbe9 275 systime_t time;
Sergunb 0:8918a71cdbe9 276 NdpContext *context;
Sergunb 0:8918a71cdbe9 277
Sergunb 0:8918a71cdbe9 278 //Point to the NDP context
Sergunb 0:8918a71cdbe9 279 context = &interface->ndpContext;
Sergunb 0:8918a71cdbe9 280
Sergunb 0:8918a71cdbe9 281 //Get current time
Sergunb 0:8918a71cdbe9 282 time = osGetSystemTime();
Sergunb 0:8918a71cdbe9 283
Sergunb 0:8918a71cdbe9 284 //When an interface becomes enabled, a host may send some Router
Sergunb 0:8918a71cdbe9 285 //Solicitation messages to obtain Router Advertisements quickly
Sergunb 0:8918a71cdbe9 286 if(interface->linkState && !interface->ipv6Context.isRouter)
Sergunb 0:8918a71cdbe9 287 {
Sergunb 0:8918a71cdbe9 288 //Make sure that a valid link-local address has been assigned to the interface
Sergunb 0:8918a71cdbe9 289 if(ipv6GetLinkLocalAddrState(interface) == IPV6_ADDR_STATE_PREFERRED)
Sergunb 0:8918a71cdbe9 290 {
Sergunb 0:8918a71cdbe9 291 //The host should transmit up to MAX_RTR_SOLICITATIONS Router
Sergunb 0:8918a71cdbe9 292 //Solicitation messages
Sergunb 0:8918a71cdbe9 293 if(context->rtrSolicitationCount == 0)
Sergunb 0:8918a71cdbe9 294 {
Sergunb 0:8918a71cdbe9 295 //Set time stamp
Sergunb 0:8918a71cdbe9 296 context->timestamp = time;
Sergunb 0:8918a71cdbe9 297
Sergunb 0:8918a71cdbe9 298 //Check whether the host has already performed Duplicate Address
Sergunb 0:8918a71cdbe9 299 //Detection for the link-local address
Sergunb 0:8918a71cdbe9 300 if(context->dupAddrDetectTransmits > 0)
Sergunb 0:8918a71cdbe9 301 {
Sergunb 0:8918a71cdbe9 302 //If a host has already performed a random delay since the interface
Sergunb 0:8918a71cdbe9 303 //became enabled, there is no need to delay again before sending the
Sergunb 0:8918a71cdbe9 304 //first Router Solicitation message
Sergunb 0:8918a71cdbe9 305 context->timeout = 0;
Sergunb 0:8918a71cdbe9 306 }
Sergunb 0:8918a71cdbe9 307 else
Sergunb 0:8918a71cdbe9 308 {
Sergunb 0:8918a71cdbe9 309 //Before a host sends an initial solicitation, it should delay the
Sergunb 0:8918a71cdbe9 310 //transmission for a random amount of time in order to alleviate
Sergunb 0:8918a71cdbe9 311 //congestion when many hosts start up on a link at the same time
Sergunb 0:8918a71cdbe9 312 context->timeout = netGetRandRange(context->minRtrSolicitationDelay,
Sergunb 0:8918a71cdbe9 313 context->maxRtrSolicitationDelay);
Sergunb 0:8918a71cdbe9 314 }
Sergunb 0:8918a71cdbe9 315
Sergunb 0:8918a71cdbe9 316 //Prepare to send the first Router Solicitation message
Sergunb 0:8918a71cdbe9 317 context->rtrSolicitationCount = 1;
Sergunb 0:8918a71cdbe9 318 }
Sergunb 0:8918a71cdbe9 319 else if(context->rtrSolicitationCount <= context->maxRtrSolicitations)
Sergunb 0:8918a71cdbe9 320 {
Sergunb 0:8918a71cdbe9 321 //Once the host sends a Router Solicitation, and receives a valid
Sergunb 0:8918a71cdbe9 322 //Router Advertisement with a non-zero Router Lifetime, the host must
Sergunb 0:8918a71cdbe9 323 //desist from sending additional solicitations on that interface
Sergunb 0:8918a71cdbe9 324 if(!context->rtrAdvReceived)
Sergunb 0:8918a71cdbe9 325 {
Sergunb 0:8918a71cdbe9 326 //Check current time
Sergunb 0:8918a71cdbe9 327 if(timeCompare(time, context->timestamp + context->timeout) >= 0)
Sergunb 0:8918a71cdbe9 328 {
Sergunb 0:8918a71cdbe9 329 //Send Router Solicitation message
Sergunb 0:8918a71cdbe9 330 ndpSendRouterSol(interface);
Sergunb 0:8918a71cdbe9 331
Sergunb 0:8918a71cdbe9 332 //Save the time at which the message was sent
Sergunb 0:8918a71cdbe9 333 context->timestamp = time;
Sergunb 0:8918a71cdbe9 334 //Set timeout value
Sergunb 0:8918a71cdbe9 335 context->timeout = context->rtrSolicitationInterval;
Sergunb 0:8918a71cdbe9 336 //Increment retransmission counter
Sergunb 0:8918a71cdbe9 337 context->rtrSolicitationCount++;
Sergunb 0:8918a71cdbe9 338 }
Sergunb 0:8918a71cdbe9 339 }
Sergunb 0:8918a71cdbe9 340 }
Sergunb 0:8918a71cdbe9 341 }
Sergunb 0:8918a71cdbe9 342 }
Sergunb 0:8918a71cdbe9 343
Sergunb 0:8918a71cdbe9 344 //Periodically update the Neighbor Cache
Sergunb 0:8918a71cdbe9 345 ndpUpdateNeighborCache(interface);
Sergunb 0:8918a71cdbe9 346
Sergunb 0:8918a71cdbe9 347 //Manage the lifetime of IPv6 addresses
Sergunb 0:8918a71cdbe9 348 ndpUpdateAddrList(interface);
Sergunb 0:8918a71cdbe9 349
Sergunb 0:8918a71cdbe9 350 //Periodically update the Prefix List
Sergunb 0:8918a71cdbe9 351 ndpUpdatePrefixList(interface);
Sergunb 0:8918a71cdbe9 352
Sergunb 0:8918a71cdbe9 353 //Periodically update the Default Router List
Sergunb 0:8918a71cdbe9 354 ndpUpdateDefaultRouterList(interface);
Sergunb 0:8918a71cdbe9 355 }
Sergunb 0:8918a71cdbe9 356
Sergunb 0:8918a71cdbe9 357
Sergunb 0:8918a71cdbe9 358 /**
Sergunb 0:8918a71cdbe9 359 * @brief Callback function for link change event
Sergunb 0:8918a71cdbe9 360 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 361 **/
Sergunb 0:8918a71cdbe9 362
Sergunb 0:8918a71cdbe9 363 void ndpLinkChangeEvent(NetInterface *interface)
Sergunb 0:8918a71cdbe9 364 {
Sergunb 0:8918a71cdbe9 365 NdpContext *context;
Sergunb 0:8918a71cdbe9 366
Sergunb 0:8918a71cdbe9 367 //Point to the NDP context
Sergunb 0:8918a71cdbe9 368 context = &interface->ndpContext;
Sergunb 0:8918a71cdbe9 369
Sergunb 0:8918a71cdbe9 370 //Restore default parameters
Sergunb 0:8918a71cdbe9 371 context->reachableTime = NDP_REACHABLE_TIME;
Sergunb 0:8918a71cdbe9 372 context->retransTimer = NDP_RETRANS_TIMER;
Sergunb 0:8918a71cdbe9 373 context->dupAddrDetectTransmits = NDP_DUP_ADDR_DETECT_TRANSMITS;
Sergunb 0:8918a71cdbe9 374 context->minRtrSolicitationDelay = NDP_MIN_RTR_SOLICITATION_DELAY;
Sergunb 0:8918a71cdbe9 375 context->maxRtrSolicitationDelay = NDP_MAX_RTR_SOLICITATION_DELAY;
Sergunb 0:8918a71cdbe9 376 context->rtrSolicitationInterval = NDP_RTR_SOLICITATION_INTERVAL;
Sergunb 0:8918a71cdbe9 377 context->maxRtrSolicitations = NDP_MAX_RTR_SOLICITATIONS;
Sergunb 0:8918a71cdbe9 378
Sergunb 0:8918a71cdbe9 379 //Reset retransmission counter for RS messages
Sergunb 0:8918a71cdbe9 380 context->rtrSolicitationCount = 0;
Sergunb 0:8918a71cdbe9 381 //Valid RA message not yet received
Sergunb 0:8918a71cdbe9 382 context->rtrAdvReceived = FALSE;
Sergunb 0:8918a71cdbe9 383
Sergunb 0:8918a71cdbe9 384 //Flush the Neighbor Cache
Sergunb 0:8918a71cdbe9 385 ndpFlushNeighborCache(interface);
Sergunb 0:8918a71cdbe9 386 //Flush the Destination Cache
Sergunb 0:8918a71cdbe9 387 ndpFlushDestCache(interface);
Sergunb 0:8918a71cdbe9 388 }
Sergunb 0:8918a71cdbe9 389
Sergunb 0:8918a71cdbe9 390
Sergunb 0:8918a71cdbe9 391 /**
Sergunb 0:8918a71cdbe9 392 * @brief Router Advertisement message processing
Sergunb 0:8918a71cdbe9 393 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 394 * @param[in] pseudoHeader IPv6 pseudo header
Sergunb 0:8918a71cdbe9 395 * @param[in] buffer Multi-part buffer containing the Router Advertisement message
Sergunb 0:8918a71cdbe9 396 * @param[in] offset Offset to the first byte of the message
Sergunb 0:8918a71cdbe9 397 * @param[in] hopLimit Hop Limit field from IPv6 header
Sergunb 0:8918a71cdbe9 398 **/
Sergunb 0:8918a71cdbe9 399
Sergunb 0:8918a71cdbe9 400 void ndpProcessRouterAdv(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader,
Sergunb 0:8918a71cdbe9 401 const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Sergunb 0:8918a71cdbe9 402 {
Sergunb 0:8918a71cdbe9 403 error_t error;
Sergunb 0:8918a71cdbe9 404 uint32_t n;
Sergunb 0:8918a71cdbe9 405 size_t length;
Sergunb 0:8918a71cdbe9 406 NdpRouterAdvMessage *message;
Sergunb 0:8918a71cdbe9 407 NdpMtuOption *mtuOption;
Sergunb 0:8918a71cdbe9 408 NdpPrefixInfoOption *prefixInfoOption;
Sergunb 0:8918a71cdbe9 409 #if (ETH_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 410 NdpLinkLayerAddrOption *linkLayerAddrOption;
Sergunb 0:8918a71cdbe9 411 NdpNeighborCacheEntry *entry;
Sergunb 0:8918a71cdbe9 412 #endif
Sergunb 0:8918a71cdbe9 413
Sergunb 0:8918a71cdbe9 414 //Retrieve the length of the message
Sergunb 0:8918a71cdbe9 415 length = netBufferGetLength(buffer) - offset;
Sergunb 0:8918a71cdbe9 416
Sergunb 0:8918a71cdbe9 417 //Check the length of the Router Advertisement message
Sergunb 0:8918a71cdbe9 418 if(length < sizeof(NdpRouterAdvMessage))
Sergunb 0:8918a71cdbe9 419 return;
Sergunb 0:8918a71cdbe9 420
Sergunb 0:8918a71cdbe9 421 //Point to the beginning of the message
Sergunb 0:8918a71cdbe9 422 message = netBufferAt(buffer, offset);
Sergunb 0:8918a71cdbe9 423 //Sanity check
Sergunb 0:8918a71cdbe9 424 if(message == NULL)
Sergunb 0:8918a71cdbe9 425 return;
Sergunb 0:8918a71cdbe9 426
Sergunb 0:8918a71cdbe9 427 //Debug message
Sergunb 0:8918a71cdbe9 428 TRACE_INFO("Router Advertisement message received (%" PRIuSIZE " bytes)...\r\n", length);
Sergunb 0:8918a71cdbe9 429 //Dump message contents for debugging purpose
Sergunb 0:8918a71cdbe9 430 ndpDumpRouterAdvMessage(message);
Sergunb 0:8918a71cdbe9 431
Sergunb 0:8918a71cdbe9 432 //Routers must use their link-local address as the source for the
Sergunb 0:8918a71cdbe9 433 //Router Advertisement so that hosts can uniquely identify routers
Sergunb 0:8918a71cdbe9 434 if(!ipv6IsLinkLocalUnicastAddr(&pseudoHeader->srcAddr))
Sergunb 0:8918a71cdbe9 435 return;
Sergunb 0:8918a71cdbe9 436
Sergunb 0:8918a71cdbe9 437 //The IPv6 Hop Limit field must have a value of 255 to ensure
Sergunb 0:8918a71cdbe9 438 //that the packet has not been forwarded by a router
Sergunb 0:8918a71cdbe9 439 if(hopLimit != NDP_HOP_LIMIT)
Sergunb 0:8918a71cdbe9 440 return;
Sergunb 0:8918a71cdbe9 441
Sergunb 0:8918a71cdbe9 442 //ICMPv6 Code must be 0. An advertisement that passes the validity
Sergunb 0:8918a71cdbe9 443 //checks is called a valid advertisement
Sergunb 0:8918a71cdbe9 444 if(message->code)
Sergunb 0:8918a71cdbe9 445 return;
Sergunb 0:8918a71cdbe9 446
Sergunb 0:8918a71cdbe9 447 //Calculate the length of the Options field
Sergunb 0:8918a71cdbe9 448 length -= sizeof(NdpRouterAdvMessage);
Sergunb 0:8918a71cdbe9 449
Sergunb 0:8918a71cdbe9 450 //Parse Options field
Sergunb 0:8918a71cdbe9 451 error = ndpCheckOptions(message->options, length);
Sergunb 0:8918a71cdbe9 452 //All included options must have a length that is greater than zero
Sergunb 0:8918a71cdbe9 453 if(error)
Sergunb 0:8918a71cdbe9 454 return;
Sergunb 0:8918a71cdbe9 455
Sergunb 0:8918a71cdbe9 456 //Check the Router Lifetime value
Sergunb 0:8918a71cdbe9 457 if(ntohs(message->routerLifetime) != 0)
Sergunb 0:8918a71cdbe9 458 {
Sergunb 0:8918a71cdbe9 459 //Add a new entry in the Default Router List
Sergunb 0:8918a71cdbe9 460 ipv6AddDefaultRouter(interface, &pseudoHeader->srcAddr,
Sergunb 0:8918a71cdbe9 461 ntohs(message->routerLifetime));
Sergunb 0:8918a71cdbe9 462
Sergunb 0:8918a71cdbe9 463 //The host should send at least one solicitation in the case where
Sergunb 0:8918a71cdbe9 464 //an advertisement is received prior to having sent a solicitation
Sergunb 0:8918a71cdbe9 465 if(interface->ndpContext.rtrSolicitationCount > 1)
Sergunb 0:8918a71cdbe9 466 {
Sergunb 0:8918a71cdbe9 467 //Once the host sends a Router Solicitation, and receives a valid
Sergunb 0:8918a71cdbe9 468 //Router Advertisement with a non-zero Router Lifetime, the host must
Sergunb 0:8918a71cdbe9 469 //desist from sending additional solicitations on that interface
Sergunb 0:8918a71cdbe9 470 interface->ndpContext.rtrAdvReceived = TRUE;
Sergunb 0:8918a71cdbe9 471 }
Sergunb 0:8918a71cdbe9 472 }
Sergunb 0:8918a71cdbe9 473 else
Sergunb 0:8918a71cdbe9 474 {
Sergunb 0:8918a71cdbe9 475 //Immediately time-out the entry
Sergunb 0:8918a71cdbe9 476 ipv6RemoveDefaultRouter(interface, &pseudoHeader->srcAddr);
Sergunb 0:8918a71cdbe9 477 }
Sergunb 0:8918a71cdbe9 478
Sergunb 0:8918a71cdbe9 479 //6LoWPAN interface?
Sergunb 0:8918a71cdbe9 480 if(interface->nicDriver->type == NIC_TYPE_6LOWPAN)
Sergunb 0:8918a71cdbe9 481 {
Sergunb 0:8918a71cdbe9 482 //In all cases, the Router Solicitation retransmissions are terminated
Sergunb 0:8918a71cdbe9 483 //when a Router Advertisement is received (refer to RFC 6675 5.3)
Sergunb 0:8918a71cdbe9 484 interface->ndpContext.rtrAdvReceived = TRUE;
Sergunb 0:8918a71cdbe9 485 }
Sergunb 0:8918a71cdbe9 486
Sergunb 0:8918a71cdbe9 487 //A Router Advertisement field (Cur Hop Limit, Reachable Time, and
Sergunb 0:8918a71cdbe9 488 //Retrans Timer) may contain a value denoting that it is unspecified.
Sergunb 0:8918a71cdbe9 489 //In such cases, the parameter should be ignored and the host should
Sergunb 0:8918a71cdbe9 490 //continue using whatever value it is already using
Sergunb 0:8918a71cdbe9 491 if(message->curHopLimit != 0)
Sergunb 0:8918a71cdbe9 492 {
Sergunb 0:8918a71cdbe9 493 //Get the default value that should be placed in the Hop Count
Sergunb 0:8918a71cdbe9 494 //field of the IP header for outgoing IP packets
Sergunb 0:8918a71cdbe9 495 interface->ipv6Context.curHopLimit = message->curHopLimit;
Sergunb 0:8918a71cdbe9 496 }
Sergunb 0:8918a71cdbe9 497
Sergunb 0:8918a71cdbe9 498 //A value of zero means unspecified...
Sergunb 0:8918a71cdbe9 499 if(message->reachableTime != 0)
Sergunb 0:8918a71cdbe9 500 {
Sergunb 0:8918a71cdbe9 501 //The Reachable Time field holds the time, in milliseconds, that
Sergunb 0:8918a71cdbe9 502 //a node assumes a neighbor is reachable after having received a
Sergunb 0:8918a71cdbe9 503 //reachability confirmation
Sergunb 0:8918a71cdbe9 504 interface->ndpContext.reachableTime = ntohl(message->reachableTime);
Sergunb 0:8918a71cdbe9 505 }
Sergunb 0:8918a71cdbe9 506
Sergunb 0:8918a71cdbe9 507 //A value of zero means unspecified...
Sergunb 0:8918a71cdbe9 508 if(message->retransTimer != 0)
Sergunb 0:8918a71cdbe9 509 {
Sergunb 0:8918a71cdbe9 510 //The Retrans Timer field holds the time, in milliseconds,
Sergunb 0:8918a71cdbe9 511 //between retransmitted Neighbor Solicitation messages
Sergunb 0:8918a71cdbe9 512 interface->ndpContext.retransTimer = ntohl(message->retransTimer);
Sergunb 0:8918a71cdbe9 513 }
Sergunb 0:8918a71cdbe9 514
Sergunb 0:8918a71cdbe9 515 #if (ETH_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 516 //Search for the Source Link-Layer Address option
Sergunb 0:8918a71cdbe9 517 linkLayerAddrOption = ndpGetOption(message->options,
Sergunb 0:8918a71cdbe9 518 length, NDP_OPT_SOURCE_LINK_LAYER_ADDR);
Sergunb 0:8918a71cdbe9 519
Sergunb 0:8918a71cdbe9 520 //Source Link-Layer Address option found?
Sergunb 0:8918a71cdbe9 521 if(linkLayerAddrOption != NULL && linkLayerAddrOption->length == 1)
Sergunb 0:8918a71cdbe9 522 {
Sergunb 0:8918a71cdbe9 523 //Debug message
Sergunb 0:8918a71cdbe9 524 TRACE_DEBUG(" Source Link-Layer Address = %s\r\n",
Sergunb 0:8918a71cdbe9 525 macAddrToString(&linkLayerAddrOption->linkLayerAddr, NULL));
Sergunb 0:8918a71cdbe9 526 }
Sergunb 0:8918a71cdbe9 527 else
Sergunb 0:8918a71cdbe9 528 {
Sergunb 0:8918a71cdbe9 529 //No valid Source Link-Layer Address option...
Sergunb 0:8918a71cdbe9 530 linkLayerAddrOption = NULL;
Sergunb 0:8918a71cdbe9 531 }
Sergunb 0:8918a71cdbe9 532
Sergunb 0:8918a71cdbe9 533 //Search the Neighbor cache for the router
Sergunb 0:8918a71cdbe9 534 entry = ndpFindNeighborCacheEntry(interface, &pseudoHeader->srcAddr);
Sergunb 0:8918a71cdbe9 535
Sergunb 0:8918a71cdbe9 536 //No matching entry has been found?
Sergunb 0:8918a71cdbe9 537 if(!entry)
Sergunb 0:8918a71cdbe9 538 {
Sergunb 0:8918a71cdbe9 539 //If the advertisement contains a Source Link-Layer Address option,
Sergunb 0:8918a71cdbe9 540 //the link-layer address should be recorded in the Neighbor cache
Sergunb 0:8918a71cdbe9 541 if(linkLayerAddrOption)
Sergunb 0:8918a71cdbe9 542 {
Sergunb 0:8918a71cdbe9 543 //Create an entry for the router
Sergunb 0:8918a71cdbe9 544 entry = ndpCreateNeighborCacheEntry(interface);
Sergunb 0:8918a71cdbe9 545
Sergunb 0:8918a71cdbe9 546 //Neighbor cache entry successfully created?
Sergunb 0:8918a71cdbe9 547 if(entry)
Sergunb 0:8918a71cdbe9 548 {
Sergunb 0:8918a71cdbe9 549 //Record the IPv6 address and the corresponding MAC address
Sergunb 0:8918a71cdbe9 550 entry->ipAddr = pseudoHeader->srcAddr;
Sergunb 0:8918a71cdbe9 551 entry->macAddr = linkLayerAddrOption->linkLayerAddr;
Sergunb 0:8918a71cdbe9 552 //The IsRouter flag must be set to TRUE
Sergunb 0:8918a71cdbe9 553 entry->isRouter = TRUE;
Sergunb 0:8918a71cdbe9 554 //Save current time
Sergunb 0:8918a71cdbe9 555 entry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 556 //The reachability state must be set to STALE
Sergunb 0:8918a71cdbe9 557 entry->state = NDP_STATE_STALE;
Sergunb 0:8918a71cdbe9 558 }
Sergunb 0:8918a71cdbe9 559 }
Sergunb 0:8918a71cdbe9 560 }
Sergunb 0:8918a71cdbe9 561 else
Sergunb 0:8918a71cdbe9 562 {
Sergunb 0:8918a71cdbe9 563 //The sender of a Router Advertisement is implicitly assumed to be a router
Sergunb 0:8918a71cdbe9 564 entry->isRouter = TRUE;
Sergunb 0:8918a71cdbe9 565
Sergunb 0:8918a71cdbe9 566 //Check if the advertisement contains a Source Link-Layer Address option
Sergunb 0:8918a71cdbe9 567 if(linkLayerAddrOption)
Sergunb 0:8918a71cdbe9 568 {
Sergunb 0:8918a71cdbe9 569 //INCOMPLETE state?
Sergunb 0:8918a71cdbe9 570 if(entry->state == NDP_STATE_INCOMPLETE)
Sergunb 0:8918a71cdbe9 571 {
Sergunb 0:8918a71cdbe9 572 //Record link-layer address
Sergunb 0:8918a71cdbe9 573 entry->macAddr = linkLayerAddrOption->linkLayerAddr;
Sergunb 0:8918a71cdbe9 574 //Send all the packets that are pending for transmission
Sergunb 0:8918a71cdbe9 575 n = ndpSendQueuedPackets(interface, entry);
Sergunb 0:8918a71cdbe9 576 //Save current time
Sergunb 0:8918a71cdbe9 577 entry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 578
Sergunb 0:8918a71cdbe9 579 //Check whether any packets have been sent
Sergunb 0:8918a71cdbe9 580 if(n > 0)
Sergunb 0:8918a71cdbe9 581 {
Sergunb 0:8918a71cdbe9 582 //Start delay timer
Sergunb 0:8918a71cdbe9 583 entry->timeout = NDP_DELAY_FIRST_PROBE_TIME;
Sergunb 0:8918a71cdbe9 584 //Switch to the DELAY state
Sergunb 0:8918a71cdbe9 585 entry->state = NDP_STATE_DELAY;
Sergunb 0:8918a71cdbe9 586 }
Sergunb 0:8918a71cdbe9 587 else
Sergunb 0:8918a71cdbe9 588 {
Sergunb 0:8918a71cdbe9 589 //Enter the STALE state
Sergunb 0:8918a71cdbe9 590 entry->state = NDP_STATE_STALE;
Sergunb 0:8918a71cdbe9 591 }
Sergunb 0:8918a71cdbe9 592 }
Sergunb 0:8918a71cdbe9 593 //REACHABLE, STALE, DELAY or PROBE state?
Sergunb 0:8918a71cdbe9 594 else
Sergunb 0:8918a71cdbe9 595 {
Sergunb 0:8918a71cdbe9 596 //Different link-layer address than cached?
Sergunb 0:8918a71cdbe9 597 if(!macCompAddr(&entry->macAddr, &linkLayerAddrOption->linkLayerAddr))
Sergunb 0:8918a71cdbe9 598 {
Sergunb 0:8918a71cdbe9 599 //Update link-layer address
Sergunb 0:8918a71cdbe9 600 entry->macAddr = linkLayerAddrOption->linkLayerAddr;
Sergunb 0:8918a71cdbe9 601 //Save current time
Sergunb 0:8918a71cdbe9 602 entry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 603 //The reachability state must be set to STALE
Sergunb 0:8918a71cdbe9 604 entry->state = NDP_STATE_STALE;
Sergunb 0:8918a71cdbe9 605 }
Sergunb 0:8918a71cdbe9 606 }
Sergunb 0:8918a71cdbe9 607 }
Sergunb 0:8918a71cdbe9 608 }
Sergunb 0:8918a71cdbe9 609 #endif
Sergunb 0:8918a71cdbe9 610
Sergunb 0:8918a71cdbe9 611 //Search for the MTU option
Sergunb 0:8918a71cdbe9 612 mtuOption = ndpGetOption(message->options, length, NDP_OPT_MTU);
Sergunb 0:8918a71cdbe9 613
Sergunb 0:8918a71cdbe9 614 //MTU option found?
Sergunb 0:8918a71cdbe9 615 if(mtuOption != NULL && mtuOption->length == 1)
Sergunb 0:8918a71cdbe9 616 {
Sergunb 0:8918a71cdbe9 617 //This option specifies the recommended MTU for the link
Sergunb 0:8918a71cdbe9 618 n = ntohl(mtuOption->mtu);
Sergunb 0:8918a71cdbe9 619
Sergunb 0:8918a71cdbe9 620 //The host should copy the option's value so long as the value is greater
Sergunb 0:8918a71cdbe9 621 //than or equal to the minimum IPv6 MTU and does not exceed the maximum
Sergunb 0:8918a71cdbe9 622 //MTU of the interface
Sergunb 0:8918a71cdbe9 623 if(n >= IPV6_DEFAULT_MTU && n <= interface->nicDriver->mtu)
Sergunb 0:8918a71cdbe9 624 {
Sergunb 0:8918a71cdbe9 625 //Save the MTU value
Sergunb 0:8918a71cdbe9 626 interface->ipv6Context.linkMtu = n;
Sergunb 0:8918a71cdbe9 627 }
Sergunb 0:8918a71cdbe9 628 }
Sergunb 0:8918a71cdbe9 629
Sergunb 0:8918a71cdbe9 630 //Point to the beginning of the Options field
Sergunb 0:8918a71cdbe9 631 n = 0;
Sergunb 0:8918a71cdbe9 632
Sergunb 0:8918a71cdbe9 633 //Parse Options field
Sergunb 0:8918a71cdbe9 634 while(1)
Sergunb 0:8918a71cdbe9 635 {
Sergunb 0:8918a71cdbe9 636 //Search the Options field for any Prefix Information options
Sergunb 0:8918a71cdbe9 637 prefixInfoOption = ndpGetOption(message->options + n,
Sergunb 0:8918a71cdbe9 638 length - n, NDP_OPT_PREFIX_INFORMATION);
Sergunb 0:8918a71cdbe9 639
Sergunb 0:8918a71cdbe9 640 //No more option of the specified type?
Sergunb 0:8918a71cdbe9 641 if(prefixInfoOption == NULL)
Sergunb 0:8918a71cdbe9 642 break;
Sergunb 0:8918a71cdbe9 643
Sergunb 0:8918a71cdbe9 644 //Hosts use the advertised on-link prefixes to build and maintain
Sergunb 0:8918a71cdbe9 645 //a list that is used in deciding when a packet's destination is
Sergunb 0:8918a71cdbe9 646 //on-link or beyond a router
Sergunb 0:8918a71cdbe9 647 ndpParsePrefixInfoOption(interface, prefixInfoOption);
Sergunb 0:8918a71cdbe9 648
Sergunb 0:8918a71cdbe9 649 //Retrieve the offset to the current position
Sergunb 0:8918a71cdbe9 650 n = (uint8_t *) prefixInfoOption - message->options;
Sergunb 0:8918a71cdbe9 651 //Jump to the next option
Sergunb 0:8918a71cdbe9 652 n += prefixInfoOption->length * 8;
Sergunb 0:8918a71cdbe9 653 }
Sergunb 0:8918a71cdbe9 654
Sergunb 0:8918a71cdbe9 655 #if (SLAAC_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 656 //Stateless Address Autoconfiguration is currently used?
Sergunb 0:8918a71cdbe9 657 if(interface->slaacContext != NULL)
Sergunb 0:8918a71cdbe9 658 {
Sergunb 0:8918a71cdbe9 659 //Process the valid advertisement
Sergunb 0:8918a71cdbe9 660 slaacParseRouterAdv(interface->slaacContext, message,
Sergunb 0:8918a71cdbe9 661 length + sizeof(NdpRouterAdvMessage));
Sergunb 0:8918a71cdbe9 662 }
Sergunb 0:8918a71cdbe9 663 #endif
Sergunb 0:8918a71cdbe9 664 }
Sergunb 0:8918a71cdbe9 665
Sergunb 0:8918a71cdbe9 666
Sergunb 0:8918a71cdbe9 667 /**
Sergunb 0:8918a71cdbe9 668 * @brief Neighbor Solicitation message processing
Sergunb 0:8918a71cdbe9 669 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 670 * @param[in] pseudoHeader IPv6 pseudo header
Sergunb 0:8918a71cdbe9 671 * @param[in] buffer Multi-part buffer containing the Neighbor Solicitation message
Sergunb 0:8918a71cdbe9 672 * @param[in] offset Offset to the first byte of the message
Sergunb 0:8918a71cdbe9 673 * @param[in] hopLimit Hop Limit field from IPv6 header
Sergunb 0:8918a71cdbe9 674 **/
Sergunb 0:8918a71cdbe9 675
Sergunb 0:8918a71cdbe9 676 void ndpProcessNeighborSol(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader,
Sergunb 0:8918a71cdbe9 677 const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Sergunb 0:8918a71cdbe9 678 {
Sergunb 0:8918a71cdbe9 679 #if (ETH_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 680 error_t error;
Sergunb 0:8918a71cdbe9 681 uint_t i;
Sergunb 0:8918a71cdbe9 682 uint_t n;
Sergunb 0:8918a71cdbe9 683 size_t length;
Sergunb 0:8918a71cdbe9 684 bool_t validTarget;
Sergunb 0:8918a71cdbe9 685 NdpNeighborSolMessage *message;
Sergunb 0:8918a71cdbe9 686 NdpLinkLayerAddrOption *option;
Sergunb 0:8918a71cdbe9 687 NdpNeighborCacheEntry *neighborCacheEntry;
Sergunb 0:8918a71cdbe9 688 Ipv6AddrEntry *addrEntry;
Sergunb 0:8918a71cdbe9 689
Sergunb 0:8918a71cdbe9 690 //Retrieve the length of the message
Sergunb 0:8918a71cdbe9 691 length = netBufferGetLength(buffer) - offset;
Sergunb 0:8918a71cdbe9 692
Sergunb 0:8918a71cdbe9 693 //Check the length of the Neighbor Solicitation message
Sergunb 0:8918a71cdbe9 694 if(length < sizeof(NdpNeighborSolMessage))
Sergunb 0:8918a71cdbe9 695 return;
Sergunb 0:8918a71cdbe9 696
Sergunb 0:8918a71cdbe9 697 //Point to the beginning of the message
Sergunb 0:8918a71cdbe9 698 message = netBufferAt(buffer, offset);
Sergunb 0:8918a71cdbe9 699 //Sanity check
Sergunb 0:8918a71cdbe9 700 if(message == NULL)
Sergunb 0:8918a71cdbe9 701 return;
Sergunb 0:8918a71cdbe9 702
Sergunb 0:8918a71cdbe9 703 //Debug message
Sergunb 0:8918a71cdbe9 704 TRACE_INFO("Neighbor Solicitation message received (%" PRIuSIZE " bytes)...\r\n", length);
Sergunb 0:8918a71cdbe9 705 //Dump message contents for debugging purpose
Sergunb 0:8918a71cdbe9 706 ndpDumpNeighborSolMessage(message);
Sergunb 0:8918a71cdbe9 707
Sergunb 0:8918a71cdbe9 708 //The IPv6 Hop Limit field must have a value of 255 to ensure
Sergunb 0:8918a71cdbe9 709 //that the packet has not been forwarded by a router
Sergunb 0:8918a71cdbe9 710 if(hopLimit != NDP_HOP_LIMIT)
Sergunb 0:8918a71cdbe9 711 return;
Sergunb 0:8918a71cdbe9 712
Sergunb 0:8918a71cdbe9 713 //ICMPv6 Code must be 0
Sergunb 0:8918a71cdbe9 714 if(message->code)
Sergunb 0:8918a71cdbe9 715 return;
Sergunb 0:8918a71cdbe9 716
Sergunb 0:8918a71cdbe9 717 //If the IP source address is the unspecified address, the IP
Sergunb 0:8918a71cdbe9 718 //destination address must be a solicited-node multicast address
Sergunb 0:8918a71cdbe9 719 if(ipv6CompAddr(&pseudoHeader->srcAddr, &IPV6_UNSPECIFIED_ADDR) &&
Sergunb 0:8918a71cdbe9 720 !ipv6IsSolicitedNodeAddr(&pseudoHeader->destAddr))
Sergunb 0:8918a71cdbe9 721 {
Sergunb 0:8918a71cdbe9 722 //Debug message
Sergunb 0:8918a71cdbe9 723 TRACE_WARNING("Destination address must be a solicited-node address!\r\n");
Sergunb 0:8918a71cdbe9 724 //Exit immediately
Sergunb 0:8918a71cdbe9 725 return;
Sergunb 0:8918a71cdbe9 726 }
Sergunb 0:8918a71cdbe9 727
Sergunb 0:8918a71cdbe9 728 //Calculate the length of the Options field
Sergunb 0:8918a71cdbe9 729 length -= sizeof(NdpNeighborSolMessage);
Sergunb 0:8918a71cdbe9 730
Sergunb 0:8918a71cdbe9 731 //Parse Options field
Sergunb 0:8918a71cdbe9 732 error = ndpCheckOptions(message->options, length);
Sergunb 0:8918a71cdbe9 733 //All included options must have a length that is greater than zero
Sergunb 0:8918a71cdbe9 734 if(error)
Sergunb 0:8918a71cdbe9 735 return;
Sergunb 0:8918a71cdbe9 736
Sergunb 0:8918a71cdbe9 737 //Search for the Source Link-Layer Address option
Sergunb 0:8918a71cdbe9 738 option = ndpGetOption(message->options,
Sergunb 0:8918a71cdbe9 739 length, NDP_OPT_SOURCE_LINK_LAYER_ADDR);
Sergunb 0:8918a71cdbe9 740
Sergunb 0:8918a71cdbe9 741 //The target address must a valid unicast or anycast address assigned to
Sergunb 0:8918a71cdbe9 742 //the interface or a tentative address on which DAD is being performed
Sergunb 0:8918a71cdbe9 743 validTarget = FALSE;
Sergunb 0:8918a71cdbe9 744
Sergunb 0:8918a71cdbe9 745 //Loop through the IPv6 addresses assigned to the interface
Sergunb 0:8918a71cdbe9 746 for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
Sergunb 0:8918a71cdbe9 747 {
Sergunb 0:8918a71cdbe9 748 //Point to the current entry
Sergunb 0:8918a71cdbe9 749 addrEntry = &interface->ipv6Context.addrList[i];
Sergunb 0:8918a71cdbe9 750
Sergunb 0:8918a71cdbe9 751 //Compare target address
Sergunb 0:8918a71cdbe9 752 if(ipv6CompAddr(&addrEntry->addr, &message->targetAddr))
Sergunb 0:8918a71cdbe9 753 {
Sergunb 0:8918a71cdbe9 754 //Check address state
Sergunb 0:8918a71cdbe9 755 if(addrEntry->state == IPV6_ADDR_STATE_TENTATIVE)
Sergunb 0:8918a71cdbe9 756 {
Sergunb 0:8918a71cdbe9 757 //If the source address of the Neighbor Solicitation is the
Sergunb 0:8918a71cdbe9 758 //unspecified address, the solicitation is from a node
Sergunb 0:8918a71cdbe9 759 //performing Duplicate Address Detection
Sergunb 0:8918a71cdbe9 760 if(ipv6CompAddr(&pseudoHeader->srcAddr, &IPV6_UNSPECIFIED_ADDR))
Sergunb 0:8918a71cdbe9 761 {
Sergunb 0:8918a71cdbe9 762 //The source link-layer address must not be included when the
Sergunb 0:8918a71cdbe9 763 //source IP address is the unspecified address...
Sergunb 0:8918a71cdbe9 764 if(option == NULL)
Sergunb 0:8918a71cdbe9 765 {
Sergunb 0:8918a71cdbe9 766 //Debug message
Sergunb 0:8918a71cdbe9 767 TRACE_WARNING("The tentative address %s is a duplicate!\r\n",
Sergunb 0:8918a71cdbe9 768 ipv6AddrToString(&addrEntry->addr, NULL));
Sergunb 0:8918a71cdbe9 769
Sergunb 0:8918a71cdbe9 770 //The tentative address is a duplicate and should not be used
Sergunb 0:8918a71cdbe9 771 addrEntry->duplicate = TRUE;
Sergunb 0:8918a71cdbe9 772 }
Sergunb 0:8918a71cdbe9 773 }
Sergunb 0:8918a71cdbe9 774
Sergunb 0:8918a71cdbe9 775 //In all cases, a node must not respond to a Neighbor Solicitation
Sergunb 0:8918a71cdbe9 776 //for a tentative address
Sergunb 0:8918a71cdbe9 777 return;
Sergunb 0:8918a71cdbe9 778 }
Sergunb 0:8918a71cdbe9 779 else if(addrEntry->state != IPV6_ADDR_STATE_INVALID)
Sergunb 0:8918a71cdbe9 780 {
Sergunb 0:8918a71cdbe9 781 //The target address is a valid address assigned to the interface
Sergunb 0:8918a71cdbe9 782 validTarget = TRUE;
Sergunb 0:8918a71cdbe9 783 //We are done
Sergunb 0:8918a71cdbe9 784 break;
Sergunb 0:8918a71cdbe9 785 }
Sergunb 0:8918a71cdbe9 786 }
Sergunb 0:8918a71cdbe9 787 }
Sergunb 0:8918a71cdbe9 788
Sergunb 0:8918a71cdbe9 789 //Invalid target address?
Sergunb 0:8918a71cdbe9 790 if(!validTarget)
Sergunb 0:8918a71cdbe9 791 {
Sergunb 0:8918a71cdbe9 792 //The Neighbor Solicitation must be discarded if the target address
Sergunb 0:8918a71cdbe9 793 //is not a valid anycast address assigned to the interface
Sergunb 0:8918a71cdbe9 794 if(!ipv6IsAnycastAddr(interface, &message->targetAddr))
Sergunb 0:8918a71cdbe9 795 {
Sergunb 0:8918a71cdbe9 796 //Debug message
Sergunb 0:8918a71cdbe9 797 TRACE_WARNING("Wrong target address!\r\n");
Sergunb 0:8918a71cdbe9 798 //Exit immediately
Sergunb 0:8918a71cdbe9 799 return;
Sergunb 0:8918a71cdbe9 800 }
Sergunb 0:8918a71cdbe9 801 }
Sergunb 0:8918a71cdbe9 802
Sergunb 0:8918a71cdbe9 803 //Source Link-Layer Address option found?
Sergunb 0:8918a71cdbe9 804 if(option != NULL && option->length == 1)
Sergunb 0:8918a71cdbe9 805 {
Sergunb 0:8918a71cdbe9 806 //Debug message
Sergunb 0:8918a71cdbe9 807 TRACE_DEBUG(" Source Link-Layer Address = %s\r\n",
Sergunb 0:8918a71cdbe9 808 macAddrToString(&option->linkLayerAddr, NULL));
Sergunb 0:8918a71cdbe9 809
Sergunb 0:8918a71cdbe9 810 //The Source Link-Layer Address option must not be included when the
Sergunb 0:8918a71cdbe9 811 //source IP address is the unspecified address
Sergunb 0:8918a71cdbe9 812 if(ipv6CompAddr(&pseudoHeader->srcAddr, &IPV6_UNSPECIFIED_ADDR))
Sergunb 0:8918a71cdbe9 813 return;
Sergunb 0:8918a71cdbe9 814
Sergunb 0:8918a71cdbe9 815 //Search the Neighbor Cache for the source address of the solicitation
Sergunb 0:8918a71cdbe9 816 neighborCacheEntry = ndpFindNeighborCacheEntry(interface, &pseudoHeader->srcAddr);
Sergunb 0:8918a71cdbe9 817
Sergunb 0:8918a71cdbe9 818 //No matching entry has been found?
Sergunb 0:8918a71cdbe9 819 if(!neighborCacheEntry)
Sergunb 0:8918a71cdbe9 820 {
Sergunb 0:8918a71cdbe9 821 //Create an entry
Sergunb 0:8918a71cdbe9 822 neighborCacheEntry = ndpCreateNeighborCacheEntry(interface);
Sergunb 0:8918a71cdbe9 823
Sergunb 0:8918a71cdbe9 824 //Neighbor Cache entry successfully created?
Sergunb 0:8918a71cdbe9 825 if(neighborCacheEntry)
Sergunb 0:8918a71cdbe9 826 {
Sergunb 0:8918a71cdbe9 827 //Record the IPv6 and the corresponding MAC address
Sergunb 0:8918a71cdbe9 828 neighborCacheEntry->ipAddr = pseudoHeader->srcAddr;
Sergunb 0:8918a71cdbe9 829 neighborCacheEntry->macAddr = option->linkLayerAddr;
Sergunb 0:8918a71cdbe9 830 //Save current time
Sergunb 0:8918a71cdbe9 831 neighborCacheEntry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 832 //Enter the STALE state
Sergunb 0:8918a71cdbe9 833 neighborCacheEntry->state = NDP_STATE_STALE;
Sergunb 0:8918a71cdbe9 834 }
Sergunb 0:8918a71cdbe9 835 }
Sergunb 0:8918a71cdbe9 836 else
Sergunb 0:8918a71cdbe9 837 {
Sergunb 0:8918a71cdbe9 838 //INCOMPLETE state?
Sergunb 0:8918a71cdbe9 839 if(neighborCacheEntry->state == NDP_STATE_INCOMPLETE)
Sergunb 0:8918a71cdbe9 840 {
Sergunb 0:8918a71cdbe9 841 //Record link-layer address
Sergunb 0:8918a71cdbe9 842 neighborCacheEntry->macAddr = option->linkLayerAddr;
Sergunb 0:8918a71cdbe9 843 //Send all the packets that are pending for transmission
Sergunb 0:8918a71cdbe9 844 n = ndpSendQueuedPackets(interface, neighborCacheEntry);
Sergunb 0:8918a71cdbe9 845 //Save current time
Sergunb 0:8918a71cdbe9 846 neighborCacheEntry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 847
Sergunb 0:8918a71cdbe9 848 //Check whether any packets have been sent
Sergunb 0:8918a71cdbe9 849 if(n > 0)
Sergunb 0:8918a71cdbe9 850 {
Sergunb 0:8918a71cdbe9 851 //Start delay timer
Sergunb 0:8918a71cdbe9 852 neighborCacheEntry->timeout = NDP_DELAY_FIRST_PROBE_TIME;
Sergunb 0:8918a71cdbe9 853 //Switch to the DELAY state
Sergunb 0:8918a71cdbe9 854 neighborCacheEntry->state = NDP_STATE_DELAY;
Sergunb 0:8918a71cdbe9 855 }
Sergunb 0:8918a71cdbe9 856 else
Sergunb 0:8918a71cdbe9 857 {
Sergunb 0:8918a71cdbe9 858 //Enter the STALE state
Sergunb 0:8918a71cdbe9 859 neighborCacheEntry->state = NDP_STATE_STALE;
Sergunb 0:8918a71cdbe9 860 }
Sergunb 0:8918a71cdbe9 861 }
Sergunb 0:8918a71cdbe9 862 //REACHABLE, STALE, DELAY or PROBE state?
Sergunb 0:8918a71cdbe9 863 else
Sergunb 0:8918a71cdbe9 864 {
Sergunb 0:8918a71cdbe9 865 //Different link-layer address than cached?
Sergunb 0:8918a71cdbe9 866 if(!macCompAddr(&neighborCacheEntry->macAddr, &option->linkLayerAddr))
Sergunb 0:8918a71cdbe9 867 {
Sergunb 0:8918a71cdbe9 868 //Update link-layer address
Sergunb 0:8918a71cdbe9 869 neighborCacheEntry->macAddr = option->linkLayerAddr;
Sergunb 0:8918a71cdbe9 870 //Save current time
Sergunb 0:8918a71cdbe9 871 neighborCacheEntry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 872 //Enter the STALE state
Sergunb 0:8918a71cdbe9 873 neighborCacheEntry->state = NDP_STATE_STALE;
Sergunb 0:8918a71cdbe9 874 }
Sergunb 0:8918a71cdbe9 875 }
Sergunb 0:8918a71cdbe9 876 }
Sergunb 0:8918a71cdbe9 877 }
Sergunb 0:8918a71cdbe9 878 //Source Link-Layer Address option not found?
Sergunb 0:8918a71cdbe9 879 else
Sergunb 0:8918a71cdbe9 880 {
Sergunb 0:8918a71cdbe9 881 //The Source Link-Layer Address option must not be included when the
Sergunb 0:8918a71cdbe9 882 //source IP address is the unspecified address. Otherwise, this option
Sergunb 0:8918a71cdbe9 883 //must be included in multicast solicitations
Sergunb 0:8918a71cdbe9 884 if(!ipv6CompAddr(&pseudoHeader->srcAddr, &IPV6_UNSPECIFIED_ADDR) &&
Sergunb 0:8918a71cdbe9 885 ipv6IsMulticastAddr(&pseudoHeader->destAddr))
Sergunb 0:8918a71cdbe9 886 {
Sergunb 0:8918a71cdbe9 887 //Debug message
Sergunb 0:8918a71cdbe9 888 TRACE_WARNING("The Source Link-Layer Address must be included!\r\n");
Sergunb 0:8918a71cdbe9 889 //Exit immediately
Sergunb 0:8918a71cdbe9 890 return;
Sergunb 0:8918a71cdbe9 891 }
Sergunb 0:8918a71cdbe9 892 }
Sergunb 0:8918a71cdbe9 893
Sergunb 0:8918a71cdbe9 894 //After any updates to the Neighbor cache, the node sends a Neighbor
Sergunb 0:8918a71cdbe9 895 //Advertisement response as described in RFC 4861 7.2.4
Sergunb 0:8918a71cdbe9 896 ndpSendNeighborAdv(interface, &message->targetAddr, &pseudoHeader->srcAddr);
Sergunb 0:8918a71cdbe9 897 #endif
Sergunb 0:8918a71cdbe9 898 }
Sergunb 0:8918a71cdbe9 899
Sergunb 0:8918a71cdbe9 900
Sergunb 0:8918a71cdbe9 901 /**
Sergunb 0:8918a71cdbe9 902 * @brief Neighbor Advertisement message processing
Sergunb 0:8918a71cdbe9 903 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 904 * @param[in] pseudoHeader IPv6 pseudo header
Sergunb 0:8918a71cdbe9 905 * @param[in] buffer Multi-part buffer containing the Neighbor Advertisement message
Sergunb 0:8918a71cdbe9 906 * @param[in] offset Offset to the first byte of the message
Sergunb 0:8918a71cdbe9 907 * @param[in] hopLimit Hop Limit field from IPv6 header
Sergunb 0:8918a71cdbe9 908 **/
Sergunb 0:8918a71cdbe9 909
Sergunb 0:8918a71cdbe9 910 void ndpProcessNeighborAdv(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader,
Sergunb 0:8918a71cdbe9 911 const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Sergunb 0:8918a71cdbe9 912 {
Sergunb 0:8918a71cdbe9 913 #if (ETH_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 914 error_t error;
Sergunb 0:8918a71cdbe9 915 uint_t i;
Sergunb 0:8918a71cdbe9 916 uint_t n;
Sergunb 0:8918a71cdbe9 917 size_t length;
Sergunb 0:8918a71cdbe9 918 bool_t differentLinkLayerAddr;
Sergunb 0:8918a71cdbe9 919 NdpNeighborAdvMessage *message;
Sergunb 0:8918a71cdbe9 920 NdpLinkLayerAddrOption *option;
Sergunb 0:8918a71cdbe9 921 NdpNeighborCacheEntry *neighborCacheEntry;
Sergunb 0:8918a71cdbe9 922 Ipv6AddrEntry *addrEntry;
Sergunb 0:8918a71cdbe9 923
Sergunb 0:8918a71cdbe9 924 //Retrieve the length of the message
Sergunb 0:8918a71cdbe9 925 length = netBufferGetLength(buffer) - offset;
Sergunb 0:8918a71cdbe9 926
Sergunb 0:8918a71cdbe9 927 //Check the length of the Neighbor Advertisement message
Sergunb 0:8918a71cdbe9 928 if(length < sizeof(NdpNeighborAdvMessage))
Sergunb 0:8918a71cdbe9 929 return;
Sergunb 0:8918a71cdbe9 930
Sergunb 0:8918a71cdbe9 931 //Point to the beginning of the message
Sergunb 0:8918a71cdbe9 932 message = netBufferAt(buffer, offset);
Sergunb 0:8918a71cdbe9 933 //Sanity check
Sergunb 0:8918a71cdbe9 934 if(message == NULL)
Sergunb 0:8918a71cdbe9 935 return;
Sergunb 0:8918a71cdbe9 936
Sergunb 0:8918a71cdbe9 937 //Debug message
Sergunb 0:8918a71cdbe9 938 TRACE_INFO("Neighbor Advertisement message received (%" PRIuSIZE " bytes)...\r\n", length);
Sergunb 0:8918a71cdbe9 939 //Dump message contents for debugging purpose
Sergunb 0:8918a71cdbe9 940 ndpDumpNeighborAdvMessage(message);
Sergunb 0:8918a71cdbe9 941
Sergunb 0:8918a71cdbe9 942 //The IPv6 Hop Limit field must have a value of 255 to ensure
Sergunb 0:8918a71cdbe9 943 //that the packet has not been forwarded by a router
Sergunb 0:8918a71cdbe9 944 if(hopLimit != NDP_HOP_LIMIT)
Sergunb 0:8918a71cdbe9 945 return;
Sergunb 0:8918a71cdbe9 946
Sergunb 0:8918a71cdbe9 947 //ICMPv6 Code must be 0
Sergunb 0:8918a71cdbe9 948 if(message->code)
Sergunb 0:8918a71cdbe9 949 return;
Sergunb 0:8918a71cdbe9 950
Sergunb 0:8918a71cdbe9 951 //The target address must not be a multicast address
Sergunb 0:8918a71cdbe9 952 if(ipv6IsMulticastAddr(&message->targetAddr))
Sergunb 0:8918a71cdbe9 953 {
Sergunb 0:8918a71cdbe9 954 //Debug message
Sergunb 0:8918a71cdbe9 955 TRACE_WARNING("Target address must not be a multicast address!\r\n");
Sergunb 0:8918a71cdbe9 956 //Exit immediately
Sergunb 0:8918a71cdbe9 957 return;
Sergunb 0:8918a71cdbe9 958 }
Sergunb 0:8918a71cdbe9 959
Sergunb 0:8918a71cdbe9 960 //If the destination address is a multicast address
Sergunb 0:8918a71cdbe9 961 //then the Solicited flag must be zero
Sergunb 0:8918a71cdbe9 962 if(ipv6IsMulticastAddr(&pseudoHeader->destAddr) && message->s)
Sergunb 0:8918a71cdbe9 963 {
Sergunb 0:8918a71cdbe9 964 //Debug message
Sergunb 0:8918a71cdbe9 965 TRACE_WARNING("Solicited flag must be zero!\r\n");
Sergunb 0:8918a71cdbe9 966 //Exit immediately
Sergunb 0:8918a71cdbe9 967 return;
Sergunb 0:8918a71cdbe9 968 }
Sergunb 0:8918a71cdbe9 969
Sergunb 0:8918a71cdbe9 970 //Calculate the length of the Options field
Sergunb 0:8918a71cdbe9 971 length -= sizeof(NdpNeighborAdvMessage);
Sergunb 0:8918a71cdbe9 972
Sergunb 0:8918a71cdbe9 973 //Parse Options field
Sergunb 0:8918a71cdbe9 974 error = ndpCheckOptions(message->options, length);
Sergunb 0:8918a71cdbe9 975 //All included options must have a length that is greater than zero
Sergunb 0:8918a71cdbe9 976 if(error)
Sergunb 0:8918a71cdbe9 977 return;
Sergunb 0:8918a71cdbe9 978
Sergunb 0:8918a71cdbe9 979 //Duplicate address detection
Sergunb 0:8918a71cdbe9 980 for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
Sergunb 0:8918a71cdbe9 981 {
Sergunb 0:8918a71cdbe9 982 //Point to the current entry
Sergunb 0:8918a71cdbe9 983 addrEntry = &interface->ipv6Context.addrList[i];
Sergunb 0:8918a71cdbe9 984
Sergunb 0:8918a71cdbe9 985 //Valid entry?
Sergunb 0:8918a71cdbe9 986 if(addrEntry->state != IPV6_ADDR_STATE_INVALID)
Sergunb 0:8918a71cdbe9 987 {
Sergunb 0:8918a71cdbe9 988 //Check whether the target address is tentative or matches
Sergunb 0:8918a71cdbe9 989 //a unicast address assigned to the interface
Sergunb 0:8918a71cdbe9 990 if(ipv6CompAddr(&addrEntry->addr, &message->targetAddr))
Sergunb 0:8918a71cdbe9 991 {
Sergunb 0:8918a71cdbe9 992 //Debug message
Sergunb 0:8918a71cdbe9 993 TRACE_WARNING("The address %s is a duplicate!\r\n",
Sergunb 0:8918a71cdbe9 994 ipv6AddrToString(&addrEntry->addr, NULL));
Sergunb 0:8918a71cdbe9 995
Sergunb 0:8918a71cdbe9 996 //The address is a duplicate and should not be used
Sergunb 0:8918a71cdbe9 997 addrEntry->duplicate = TRUE;
Sergunb 0:8918a71cdbe9 998 //Exit immediately
Sergunb 0:8918a71cdbe9 999 return;
Sergunb 0:8918a71cdbe9 1000 }
Sergunb 0:8918a71cdbe9 1001 }
Sergunb 0:8918a71cdbe9 1002 }
Sergunb 0:8918a71cdbe9 1003
Sergunb 0:8918a71cdbe9 1004 //Search the Neighbor cache for the specified target address
Sergunb 0:8918a71cdbe9 1005 neighborCacheEntry = ndpFindNeighborCacheEntry(interface, &message->targetAddr);
Sergunb 0:8918a71cdbe9 1006
Sergunb 0:8918a71cdbe9 1007 //If no entry exists, the advertisement should be silently discarded
Sergunb 0:8918a71cdbe9 1008 if(neighborCacheEntry)
Sergunb 0:8918a71cdbe9 1009 {
Sergunb 0:8918a71cdbe9 1010 //This flag tells whether the supplied link-layer
Sergunb 0:8918a71cdbe9 1011 //address differs from that in the cache
Sergunb 0:8918a71cdbe9 1012 differentLinkLayerAddr = FALSE;
Sergunb 0:8918a71cdbe9 1013
Sergunb 0:8918a71cdbe9 1014 //Search for the Target Link-Layer Address option
Sergunb 0:8918a71cdbe9 1015 option = ndpGetOption(message->options,
Sergunb 0:8918a71cdbe9 1016 length, NDP_OPT_TARGET_LINK_LAYER_ADDR);
Sergunb 0:8918a71cdbe9 1017
Sergunb 0:8918a71cdbe9 1018 //Target Link-Layer Address option found?
Sergunb 0:8918a71cdbe9 1019 if(option != NULL && option->length == 1)
Sergunb 0:8918a71cdbe9 1020 {
Sergunb 0:8918a71cdbe9 1021 //Debug message
Sergunb 0:8918a71cdbe9 1022 TRACE_DEBUG(" Target Link-Layer Address = %s\r\n",
Sergunb 0:8918a71cdbe9 1023 macAddrToString(&option->linkLayerAddr, NULL));
Sergunb 0:8918a71cdbe9 1024
Sergunb 0:8918a71cdbe9 1025 //Different link-layer address than cached?
Sergunb 0:8918a71cdbe9 1026 if(!macCompAddr(&neighborCacheEntry->macAddr, &option->linkLayerAddr))
Sergunb 0:8918a71cdbe9 1027 differentLinkLayerAddr = TRUE;
Sergunb 0:8918a71cdbe9 1028 }
Sergunb 0:8918a71cdbe9 1029
Sergunb 0:8918a71cdbe9 1030 //INCOMPLETE state?
Sergunb 0:8918a71cdbe9 1031 if(neighborCacheEntry->state == NDP_STATE_INCOMPLETE)
Sergunb 0:8918a71cdbe9 1032 {
Sergunb 0:8918a71cdbe9 1033 //If no Target Link-Layer Address option is included, the receiving
Sergunb 0:8918a71cdbe9 1034 //node should silently discard the received advertisement
Sergunb 0:8918a71cdbe9 1035 if(option != NULL && option->length == 1)
Sergunb 0:8918a71cdbe9 1036 {
Sergunb 0:8918a71cdbe9 1037 //Record the link-layer address
Sergunb 0:8918a71cdbe9 1038 neighborCacheEntry->macAddr = option->linkLayerAddr;
Sergunb 0:8918a71cdbe9 1039 //Send all the packets that are pending for transmission
Sergunb 0:8918a71cdbe9 1040 n = ndpSendQueuedPackets(interface, neighborCacheEntry);
Sergunb 0:8918a71cdbe9 1041 //Save current time
Sergunb 0:8918a71cdbe9 1042 neighborCacheEntry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 1043
Sergunb 0:8918a71cdbe9 1044 //Solicited flag is set?
Sergunb 0:8918a71cdbe9 1045 if(message->s)
Sergunb 0:8918a71cdbe9 1046 {
Sergunb 0:8918a71cdbe9 1047 //Computing the random ReachableTime value
Sergunb 0:8918a71cdbe9 1048 neighborCacheEntry->timeout = interface->ndpContext.reachableTime;
Sergunb 0:8918a71cdbe9 1049 //Switch to the REACHABLE state
Sergunb 0:8918a71cdbe9 1050 neighborCacheEntry->state = NDP_STATE_REACHABLE;
Sergunb 0:8918a71cdbe9 1051 }
Sergunb 0:8918a71cdbe9 1052 else
Sergunb 0:8918a71cdbe9 1053 {
Sergunb 0:8918a71cdbe9 1054 //Check whether any packets have been sent
Sergunb 0:8918a71cdbe9 1055 if(n > 0)
Sergunb 0:8918a71cdbe9 1056 {
Sergunb 0:8918a71cdbe9 1057 //Start delay timer
Sergunb 0:8918a71cdbe9 1058 neighborCacheEntry->timeout = NDP_DELAY_FIRST_PROBE_TIME;
Sergunb 0:8918a71cdbe9 1059 //Switch to the DELAY state
Sergunb 0:8918a71cdbe9 1060 neighborCacheEntry->state = NDP_STATE_DELAY;
Sergunb 0:8918a71cdbe9 1061 }
Sergunb 0:8918a71cdbe9 1062 else
Sergunb 0:8918a71cdbe9 1063 {
Sergunb 0:8918a71cdbe9 1064 //Enter the STALE state
Sergunb 0:8918a71cdbe9 1065 neighborCacheEntry->state = NDP_STATE_STALE;
Sergunb 0:8918a71cdbe9 1066 }
Sergunb 0:8918a71cdbe9 1067 }
Sergunb 0:8918a71cdbe9 1068 }
Sergunb 0:8918a71cdbe9 1069 }
Sergunb 0:8918a71cdbe9 1070 //REACHABLE, STALE, DELAY or PROBE state?
Sergunb 0:8918a71cdbe9 1071 else
Sergunb 0:8918a71cdbe9 1072 {
Sergunb 0:8918a71cdbe9 1073 //Check whether the Override flag is clear and the supplied
Sergunb 0:8918a71cdbe9 1074 //link-layer address differs from that in the cache
Sergunb 0:8918a71cdbe9 1075 if(!message->o && differentLinkLayerAddr)
Sergunb 0:8918a71cdbe9 1076 {
Sergunb 0:8918a71cdbe9 1077 //REACHABLE state?
Sergunb 0:8918a71cdbe9 1078 if(neighborCacheEntry->state == NDP_STATE_REACHABLE)
Sergunb 0:8918a71cdbe9 1079 {
Sergunb 0:8918a71cdbe9 1080 //Save current time
Sergunb 0:8918a71cdbe9 1081 neighborCacheEntry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 1082 //Enter the STALE state
Sergunb 0:8918a71cdbe9 1083 neighborCacheEntry->state = NDP_STATE_STALE;
Sergunb 0:8918a71cdbe9 1084 }
Sergunb 0:8918a71cdbe9 1085 }
Sergunb 0:8918a71cdbe9 1086 else
Sergunb 0:8918a71cdbe9 1087 {
Sergunb 0:8918a71cdbe9 1088 //Solicited flag is set?
Sergunb 0:8918a71cdbe9 1089 if(message->s)
Sergunb 0:8918a71cdbe9 1090 {
Sergunb 0:8918a71cdbe9 1091 //Different link-layer address than cached?
Sergunb 0:8918a71cdbe9 1092 if(differentLinkLayerAddr)
Sergunb 0:8918a71cdbe9 1093 {
Sergunb 0:8918a71cdbe9 1094 //The link-layer address must be inserted in the cache
Sergunb 0:8918a71cdbe9 1095 neighborCacheEntry->macAddr = option->linkLayerAddr;
Sergunb 0:8918a71cdbe9 1096 }
Sergunb 0:8918a71cdbe9 1097
Sergunb 0:8918a71cdbe9 1098 //Save current time
Sergunb 0:8918a71cdbe9 1099 neighborCacheEntry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 1100 //Computing the random ReachableTime value
Sergunb 0:8918a71cdbe9 1101 neighborCacheEntry->timeout = interface->ndpContext.reachableTime;
Sergunb 0:8918a71cdbe9 1102 //Switch to the REACHABLE state
Sergunb 0:8918a71cdbe9 1103 neighborCacheEntry->state = NDP_STATE_REACHABLE;
Sergunb 0:8918a71cdbe9 1104 }
Sergunb 0:8918a71cdbe9 1105 else
Sergunb 0:8918a71cdbe9 1106 {
Sergunb 0:8918a71cdbe9 1107 //Different link-layer address than cached?
Sergunb 0:8918a71cdbe9 1108 if(differentLinkLayerAddr)
Sergunb 0:8918a71cdbe9 1109 {
Sergunb 0:8918a71cdbe9 1110 //The link-layer address must be inserted in the cache
Sergunb 0:8918a71cdbe9 1111 neighborCacheEntry->macAddr = option->linkLayerAddr;
Sergunb 0:8918a71cdbe9 1112 //Save current time
Sergunb 0:8918a71cdbe9 1113 neighborCacheEntry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 1114 //The state must be set to STALE
Sergunb 0:8918a71cdbe9 1115 neighborCacheEntry->state = NDP_STATE_STALE;
Sergunb 0:8918a71cdbe9 1116 }
Sergunb 0:8918a71cdbe9 1117 }
Sergunb 0:8918a71cdbe9 1118 }
Sergunb 0:8918a71cdbe9 1119 }
Sergunb 0:8918a71cdbe9 1120
Sergunb 0:8918a71cdbe9 1121 //The IsRouter flag in the cache entry must be set based
Sergunb 0:8918a71cdbe9 1122 //on the Router flag in the received advertisement
Sergunb 0:8918a71cdbe9 1123 if(message->r)
Sergunb 0:8918a71cdbe9 1124 {
Sergunb 0:8918a71cdbe9 1125 //The neighbor is a router
Sergunb 0:8918a71cdbe9 1126 neighborCacheEntry->isRouter = TRUE;
Sergunb 0:8918a71cdbe9 1127 }
Sergunb 0:8918a71cdbe9 1128 else
Sergunb 0:8918a71cdbe9 1129 {
Sergunb 0:8918a71cdbe9 1130 //Check whether the IsRouter flag changes from TRUE to FALSE
Sergunb 0:8918a71cdbe9 1131 //as a result of this update
Sergunb 0:8918a71cdbe9 1132 if(neighborCacheEntry->isRouter)
Sergunb 0:8918a71cdbe9 1133 {
Sergunb 0:8918a71cdbe9 1134 //The node must remove that router from the Default Router list
Sergunb 0:8918a71cdbe9 1135 //and update the Destination cache entries for all destinations
Sergunb 0:8918a71cdbe9 1136 //using that neighbor as a router
Sergunb 0:8918a71cdbe9 1137 ipv6RemoveDefaultRouter(interface, &neighborCacheEntry->ipAddr);
Sergunb 0:8918a71cdbe9 1138 }
Sergunb 0:8918a71cdbe9 1139
Sergunb 0:8918a71cdbe9 1140 //The neighbor is a host
Sergunb 0:8918a71cdbe9 1141 neighborCacheEntry->isRouter = FALSE;
Sergunb 0:8918a71cdbe9 1142 }
Sergunb 0:8918a71cdbe9 1143 }
Sergunb 0:8918a71cdbe9 1144 #endif
Sergunb 0:8918a71cdbe9 1145 }
Sergunb 0:8918a71cdbe9 1146
Sergunb 0:8918a71cdbe9 1147
Sergunb 0:8918a71cdbe9 1148 /**
Sergunb 0:8918a71cdbe9 1149 * @brief Redirect message processing
Sergunb 0:8918a71cdbe9 1150 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 1151 * @param[in] pseudoHeader IPv6 pseudo header
Sergunb 0:8918a71cdbe9 1152 * @param[in] buffer Multi-part buffer containing the Redirect message
Sergunb 0:8918a71cdbe9 1153 * @param[in] offset Offset to the first byte of the message
Sergunb 0:8918a71cdbe9 1154 * @param[in] hopLimit Hop Limit field from IPv6 header
Sergunb 0:8918a71cdbe9 1155 **/
Sergunb 0:8918a71cdbe9 1156
Sergunb 0:8918a71cdbe9 1157 void ndpProcessRedirect(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader,
Sergunb 0:8918a71cdbe9 1158 const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Sergunb 0:8918a71cdbe9 1159 {
Sergunb 0:8918a71cdbe9 1160 #if (ETH_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 1161 error_t error;
Sergunb 0:8918a71cdbe9 1162 uint_t n;
Sergunb 0:8918a71cdbe9 1163 size_t length;
Sergunb 0:8918a71cdbe9 1164 NdpRedirectMessage *message;
Sergunb 0:8918a71cdbe9 1165 NdpLinkLayerAddrOption *option;
Sergunb 0:8918a71cdbe9 1166 NdpNeighborCacheEntry *neighborCacheEntry;
Sergunb 0:8918a71cdbe9 1167 NdpDestCacheEntry *destCacheEntry;
Sergunb 0:8918a71cdbe9 1168
Sergunb 0:8918a71cdbe9 1169 //Retrieve the length of the message
Sergunb 0:8918a71cdbe9 1170 length = netBufferGetLength(buffer) - offset;
Sergunb 0:8918a71cdbe9 1171
Sergunb 0:8918a71cdbe9 1172 //Check the length of the Redirect message
Sergunb 0:8918a71cdbe9 1173 if(length < sizeof(NdpRedirectMessage))
Sergunb 0:8918a71cdbe9 1174 return;
Sergunb 0:8918a71cdbe9 1175
Sergunb 0:8918a71cdbe9 1176 //Point to the beginning of the message
Sergunb 0:8918a71cdbe9 1177 message = netBufferAt(buffer, offset);
Sergunb 0:8918a71cdbe9 1178 //Sanity check
Sergunb 0:8918a71cdbe9 1179 if(message == NULL)
Sergunb 0:8918a71cdbe9 1180 return;
Sergunb 0:8918a71cdbe9 1181
Sergunb 0:8918a71cdbe9 1182 //Debug message
Sergunb 0:8918a71cdbe9 1183 TRACE_INFO("Redirect message received (%" PRIuSIZE " bytes)...\r\n", length);
Sergunb 0:8918a71cdbe9 1184 //Dump message contents for debugging purpose
Sergunb 0:8918a71cdbe9 1185 ndpDumpRedirectMessage(message);
Sergunb 0:8918a71cdbe9 1186
Sergunb 0:8918a71cdbe9 1187 //The IPv6 Hop Limit field must have a value of 255 to ensure
Sergunb 0:8918a71cdbe9 1188 //that the packet has not been forwarded by a router
Sergunb 0:8918a71cdbe9 1189 if(hopLimit != NDP_HOP_LIMIT)
Sergunb 0:8918a71cdbe9 1190 return;
Sergunb 0:8918a71cdbe9 1191
Sergunb 0:8918a71cdbe9 1192 //ICMPv6 Code must be 0
Sergunb 0:8918a71cdbe9 1193 if(message->code)
Sergunb 0:8918a71cdbe9 1194 return;
Sergunb 0:8918a71cdbe9 1195
Sergunb 0:8918a71cdbe9 1196 //Routers must use their link-local address as the source for Redirect
Sergunb 0:8918a71cdbe9 1197 //messages so that hosts can uniquely identify routers
Sergunb 0:8918a71cdbe9 1198 if(!ipv6IsLinkLocalUnicastAddr(&pseudoHeader->srcAddr))
Sergunb 0:8918a71cdbe9 1199 return;
Sergunb 0:8918a71cdbe9 1200
Sergunb 0:8918a71cdbe9 1201 //The IP source address of the Redirect must be the same as the current
Sergunb 0:8918a71cdbe9 1202 //first-hop router for the specified Destination address
Sergunb 0:8918a71cdbe9 1203 if(!ndpIsFirstHopRouter(interface, &message->destAddr, &pseudoHeader->srcAddr))
Sergunb 0:8918a71cdbe9 1204 return;
Sergunb 0:8918a71cdbe9 1205
Sergunb 0:8918a71cdbe9 1206 //The Destination Address field in the Redirect message must not
Sergunb 0:8918a71cdbe9 1207 //contain a multicast address
Sergunb 0:8918a71cdbe9 1208 if(ipv6IsMulticastAddr(&message->destAddr))
Sergunb 0:8918a71cdbe9 1209 return;
Sergunb 0:8918a71cdbe9 1210
Sergunb 0:8918a71cdbe9 1211 //The Target Address must be either a link-local address (when redirected
Sergunb 0:8918a71cdbe9 1212 //to a router) or the same as the Destination Address (when redirected to
Sergunb 0:8918a71cdbe9 1213 //the on-link destination)
Sergunb 0:8918a71cdbe9 1214 if(!ipv6IsLinkLocalUnicastAddr(&message->targetAddr) &&
Sergunb 0:8918a71cdbe9 1215 !ipv6CompAddr(&message->targetAddr, &message->destAddr))
Sergunb 0:8918a71cdbe9 1216 {
Sergunb 0:8918a71cdbe9 1217 //Silently discard the received Redirect message
Sergunb 0:8918a71cdbe9 1218 return;
Sergunb 0:8918a71cdbe9 1219 }
Sergunb 0:8918a71cdbe9 1220
Sergunb 0:8918a71cdbe9 1221 //Calculate the length of the Options field
Sergunb 0:8918a71cdbe9 1222 length -= sizeof(NdpNeighborAdvMessage);
Sergunb 0:8918a71cdbe9 1223
Sergunb 0:8918a71cdbe9 1224 //Parse Options field
Sergunb 0:8918a71cdbe9 1225 error = ndpCheckOptions(message->options, length);
Sergunb 0:8918a71cdbe9 1226 //All included options must have a length that is greater than zero
Sergunb 0:8918a71cdbe9 1227 if(error)
Sergunb 0:8918a71cdbe9 1228 return;
Sergunb 0:8918a71cdbe9 1229
Sergunb 0:8918a71cdbe9 1230 //Search the Destination cache for the specified address
Sergunb 0:8918a71cdbe9 1231 destCacheEntry = ndpFindDestCacheEntry(interface, &message->destAddr);
Sergunb 0:8918a71cdbe9 1232
Sergunb 0:8918a71cdbe9 1233 //Check whether a corresponding Destination cache entry exists
Sergunb 0:8918a71cdbe9 1234 if(destCacheEntry)
Sergunb 0:8918a71cdbe9 1235 {
Sergunb 0:8918a71cdbe9 1236 //The entry is updated with information learned from Redirect messages
Sergunb 0:8918a71cdbe9 1237 destCacheEntry->nextHop = message->targetAddr;
Sergunb 0:8918a71cdbe9 1238 //Save current time
Sergunb 0:8918a71cdbe9 1239 destCacheEntry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 1240 }
Sergunb 0:8918a71cdbe9 1241 else
Sergunb 0:8918a71cdbe9 1242 {
Sergunb 0:8918a71cdbe9 1243 //If no Destination Cache entry exists for the destination, an
Sergunb 0:8918a71cdbe9 1244 //implementation should create such an entry
Sergunb 0:8918a71cdbe9 1245 destCacheEntry = ndpCreateDestCacheEntry(interface);
Sergunb 0:8918a71cdbe9 1246
Sergunb 0:8918a71cdbe9 1247 //Destination cache entry successfully created?
Sergunb 0:8918a71cdbe9 1248 if(destCacheEntry)
Sergunb 0:8918a71cdbe9 1249 {
Sergunb 0:8918a71cdbe9 1250 //Destination address
Sergunb 0:8918a71cdbe9 1251 destCacheEntry->destAddr = message->destAddr;
Sergunb 0:8918a71cdbe9 1252 //Address of the next hop
Sergunb 0:8918a71cdbe9 1253 destCacheEntry->nextHop = message->targetAddr;
Sergunb 0:8918a71cdbe9 1254
Sergunb 0:8918a71cdbe9 1255 //Initially, the PMTU value for a path is assumed to be
Sergunb 0:8918a71cdbe9 1256 //the MTU of the first-hop link
Sergunb 0:8918a71cdbe9 1257 destCacheEntry->pathMtu = interface->ipv6Context.linkMtu;
Sergunb 0:8918a71cdbe9 1258
Sergunb 0:8918a71cdbe9 1259 //Save current time
Sergunb 0:8918a71cdbe9 1260 destCacheEntry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 1261 }
Sergunb 0:8918a71cdbe9 1262 }
Sergunb 0:8918a71cdbe9 1263
Sergunb 0:8918a71cdbe9 1264 //Search for the Target Link-Layer Address option
Sergunb 0:8918a71cdbe9 1265 option = ndpGetOption(message->options,
Sergunb 0:8918a71cdbe9 1266 length, NDP_OPT_TARGET_LINK_LAYER_ADDR);
Sergunb 0:8918a71cdbe9 1267
Sergunb 0:8918a71cdbe9 1268 //If the Redirect contains a Target Link-Layer Address option, the host
Sergunb 0:8918a71cdbe9 1269 //either creates or updates the Neighbor Cache entry for the target
Sergunb 0:8918a71cdbe9 1270 if(option != NULL && option->length == 1)
Sergunb 0:8918a71cdbe9 1271 {
Sergunb 0:8918a71cdbe9 1272 //Debug message
Sergunb 0:8918a71cdbe9 1273 TRACE_DEBUG(" Target Link-Layer Address = %s\r\n",
Sergunb 0:8918a71cdbe9 1274 macAddrToString(&option->linkLayerAddr, NULL));
Sergunb 0:8918a71cdbe9 1275
Sergunb 0:8918a71cdbe9 1276 //Search the Neighbor cache for the specified target address
Sergunb 0:8918a71cdbe9 1277 neighborCacheEntry = ndpFindNeighborCacheEntry(interface, &message->targetAddr);
Sergunb 0:8918a71cdbe9 1278
Sergunb 0:8918a71cdbe9 1279 //No matching entry has been found?
Sergunb 0:8918a71cdbe9 1280 if(!neighborCacheEntry)
Sergunb 0:8918a71cdbe9 1281 {
Sergunb 0:8918a71cdbe9 1282 //Create an entry for the target
Sergunb 0:8918a71cdbe9 1283 neighborCacheEntry = ndpCreateNeighborCacheEntry(interface);
Sergunb 0:8918a71cdbe9 1284
Sergunb 0:8918a71cdbe9 1285 //Neighbor cache entry successfully created?
Sergunb 0:8918a71cdbe9 1286 if(neighborCacheEntry)
Sergunb 0:8918a71cdbe9 1287 {
Sergunb 0:8918a71cdbe9 1288 //Record the Target address
Sergunb 0:8918a71cdbe9 1289 neighborCacheEntry->ipAddr = message->targetAddr;
Sergunb 0:8918a71cdbe9 1290 //The cached link-layer address is copied from the option
Sergunb 0:8918a71cdbe9 1291 neighborCacheEntry->macAddr = option->linkLayerAddr;
Sergunb 0:8918a71cdbe9 1292 //Newly created Neighbor Cache entries should set the IsRouter flag to FALSE
Sergunb 0:8918a71cdbe9 1293 neighborCacheEntry->isRouter = FALSE;
Sergunb 0:8918a71cdbe9 1294 //Save current time
Sergunb 0:8918a71cdbe9 1295 neighborCacheEntry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 1296 //The reachability state must be set to STALE
Sergunb 0:8918a71cdbe9 1297 neighborCacheEntry->state = NDP_STATE_STALE;
Sergunb 0:8918a71cdbe9 1298 }
Sergunb 0:8918a71cdbe9 1299 }
Sergunb 0:8918a71cdbe9 1300 else
Sergunb 0:8918a71cdbe9 1301 {
Sergunb 0:8918a71cdbe9 1302 //If the Target Address is not the same as the Destination Address,
Sergunb 0:8918a71cdbe9 1303 //the host must set IsRouter to TRUE for the target
Sergunb 0:8918a71cdbe9 1304 if(!ipv6CompAddr(&message->targetAddr, &message->destAddr))
Sergunb 0:8918a71cdbe9 1305 neighborCacheEntry->isRouter = TRUE;
Sergunb 0:8918a71cdbe9 1306
Sergunb 0:8918a71cdbe9 1307 //INCOMPLETE state?
Sergunb 0:8918a71cdbe9 1308 if(neighborCacheEntry->state == NDP_STATE_INCOMPLETE)
Sergunb 0:8918a71cdbe9 1309 {
Sergunb 0:8918a71cdbe9 1310 //Record link-layer address
Sergunb 0:8918a71cdbe9 1311 neighborCacheEntry->macAddr = option->linkLayerAddr;
Sergunb 0:8918a71cdbe9 1312 //Send all the packets that are pending for transmission
Sergunb 0:8918a71cdbe9 1313 n = ndpSendQueuedPackets(interface, neighborCacheEntry);
Sergunb 0:8918a71cdbe9 1314 //Save current time
Sergunb 0:8918a71cdbe9 1315 neighborCacheEntry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 1316
Sergunb 0:8918a71cdbe9 1317 //Check whether any packets have been sent
Sergunb 0:8918a71cdbe9 1318 if(n > 0)
Sergunb 0:8918a71cdbe9 1319 {
Sergunb 0:8918a71cdbe9 1320 //Start delay timer
Sergunb 0:8918a71cdbe9 1321 neighborCacheEntry->timeout = NDP_DELAY_FIRST_PROBE_TIME;
Sergunb 0:8918a71cdbe9 1322 //Switch to the DELAY state
Sergunb 0:8918a71cdbe9 1323 neighborCacheEntry->state = NDP_STATE_DELAY;
Sergunb 0:8918a71cdbe9 1324 }
Sergunb 0:8918a71cdbe9 1325 else
Sergunb 0:8918a71cdbe9 1326 {
Sergunb 0:8918a71cdbe9 1327 //Enter the STALE state
Sergunb 0:8918a71cdbe9 1328 neighborCacheEntry->state = NDP_STATE_STALE;
Sergunb 0:8918a71cdbe9 1329 }
Sergunb 0:8918a71cdbe9 1330 }
Sergunb 0:8918a71cdbe9 1331 //REACHABLE, STALE, DELAY or PROBE state?
Sergunb 0:8918a71cdbe9 1332 else
Sergunb 0:8918a71cdbe9 1333 {
Sergunb 0:8918a71cdbe9 1334 //Different link-layer address than cached?
Sergunb 0:8918a71cdbe9 1335 if(!macCompAddr(&neighborCacheEntry->macAddr, &option->linkLayerAddr))
Sergunb 0:8918a71cdbe9 1336 {
Sergunb 0:8918a71cdbe9 1337 //Update link-layer address
Sergunb 0:8918a71cdbe9 1338 neighborCacheEntry->macAddr = option->linkLayerAddr;
Sergunb 0:8918a71cdbe9 1339 //Save current time
Sergunb 0:8918a71cdbe9 1340 neighborCacheEntry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 1341 //The reachability state must be set to STALE
Sergunb 0:8918a71cdbe9 1342 neighborCacheEntry->state = NDP_STATE_STALE;
Sergunb 0:8918a71cdbe9 1343 }
Sergunb 0:8918a71cdbe9 1344 }
Sergunb 0:8918a71cdbe9 1345 }
Sergunb 0:8918a71cdbe9 1346 }
Sergunb 0:8918a71cdbe9 1347 #endif
Sergunb 0:8918a71cdbe9 1348 }
Sergunb 0:8918a71cdbe9 1349
Sergunb 0:8918a71cdbe9 1350
Sergunb 0:8918a71cdbe9 1351 /**
Sergunb 0:8918a71cdbe9 1352 * @brief Send a Router Solicitation message
Sergunb 0:8918a71cdbe9 1353 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 1354 * @return Error code
Sergunb 0:8918a71cdbe9 1355 **/
Sergunb 0:8918a71cdbe9 1356
Sergunb 0:8918a71cdbe9 1357 error_t ndpSendRouterSol(NetInterface *interface)
Sergunb 0:8918a71cdbe9 1358 {
Sergunb 0:8918a71cdbe9 1359 error_t error;
Sergunb 0:8918a71cdbe9 1360 size_t offset;
Sergunb 0:8918a71cdbe9 1361 size_t length;
Sergunb 0:8918a71cdbe9 1362 NetBuffer *buffer;
Sergunb 0:8918a71cdbe9 1363 NdpRouterSolMessage *message;
Sergunb 0:8918a71cdbe9 1364 Ipv6PseudoHeader pseudoHeader;
Sergunb 0:8918a71cdbe9 1365
Sergunb 0:8918a71cdbe9 1366 //The destination address is typically the all-routers multicast address
Sergunb 0:8918a71cdbe9 1367 pseudoHeader.destAddr = IPV6_LINK_LOCAL_ALL_ROUTERS_ADDR;
Sergunb 0:8918a71cdbe9 1368
Sergunb 0:8918a71cdbe9 1369 //Select the most appropriate source address to be used when
Sergunb 0:8918a71cdbe9 1370 //sending the Router Solicitation message
Sergunb 0:8918a71cdbe9 1371 error = ipv6SelectSourceAddr(&interface,
Sergunb 0:8918a71cdbe9 1372 &pseudoHeader.destAddr, &pseudoHeader.srcAddr);
Sergunb 0:8918a71cdbe9 1373
Sergunb 0:8918a71cdbe9 1374 //No address assigned to the interface?
Sergunb 0:8918a71cdbe9 1375 if(error)
Sergunb 0:8918a71cdbe9 1376 {
Sergunb 0:8918a71cdbe9 1377 //Use the unspecified address if no address is assigned
Sergunb 0:8918a71cdbe9 1378 //to the sending interface
Sergunb 0:8918a71cdbe9 1379 pseudoHeader.srcAddr = IPV6_UNSPECIFIED_ADDR;
Sergunb 0:8918a71cdbe9 1380 }
Sergunb 0:8918a71cdbe9 1381
Sergunb 0:8918a71cdbe9 1382 //The only defined option that may appear in a Router Solicitation
Sergunb 0:8918a71cdbe9 1383 //message is the Source Link-Layer Address option
Sergunb 0:8918a71cdbe9 1384 length = sizeof(NdpRouterSolMessage) + sizeof(NdpLinkLayerAddrOption);
Sergunb 0:8918a71cdbe9 1385
Sergunb 0:8918a71cdbe9 1386 //Allocate a memory buffer to hold the Router Solicitation message
Sergunb 0:8918a71cdbe9 1387 buffer = ipAllocBuffer(length, &offset);
Sergunb 0:8918a71cdbe9 1388 //Failed to allocate memory?
Sergunb 0:8918a71cdbe9 1389 if(buffer == NULL)
Sergunb 0:8918a71cdbe9 1390 return ERROR_OUT_OF_MEMORY;
Sergunb 0:8918a71cdbe9 1391
Sergunb 0:8918a71cdbe9 1392 //Point to the beginning of the message
Sergunb 0:8918a71cdbe9 1393 message = netBufferAt(buffer, offset);
Sergunb 0:8918a71cdbe9 1394
Sergunb 0:8918a71cdbe9 1395 //Format Router Solicitation message
Sergunb 0:8918a71cdbe9 1396 message->type = ICMPV6_TYPE_ROUTER_SOL;
Sergunb 0:8918a71cdbe9 1397 message->code = 0;
Sergunb 0:8918a71cdbe9 1398 message->checksum = 0;
Sergunb 0:8918a71cdbe9 1399 message->reserved = 0;
Sergunb 0:8918a71cdbe9 1400
Sergunb 0:8918a71cdbe9 1401 //Length of the message, excluding any option
Sergunb 0:8918a71cdbe9 1402 length = sizeof(NdpRouterSolMessage);
Sergunb 0:8918a71cdbe9 1403
Sergunb 0:8918a71cdbe9 1404 //The Source Link-Layer Address option must not be included
Sergunb 0:8918a71cdbe9 1405 //when the source IPv6 address is the unspecified address
Sergunb 0:8918a71cdbe9 1406 if(!ipv6CompAddr(&pseudoHeader.srcAddr, &IPV6_UNSPECIFIED_ADDR))
Sergunb 0:8918a71cdbe9 1407 {
Sergunb 0:8918a71cdbe9 1408 #if (ETH_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 1409 //Check whether a MAC address has been assigned to the interface
Sergunb 0:8918a71cdbe9 1410 if(!macCompAddr(&interface->macAddr, &MAC_UNSPECIFIED_ADDR))
Sergunb 0:8918a71cdbe9 1411 {
Sergunb 0:8918a71cdbe9 1412 //Add Source Link-Layer Address option
Sergunb 0:8918a71cdbe9 1413 ndpAddOption(message, &length, NDP_OPT_SOURCE_LINK_LAYER_ADDR,
Sergunb 0:8918a71cdbe9 1414 &interface->macAddr, sizeof(MacAddr));
Sergunb 0:8918a71cdbe9 1415 }
Sergunb 0:8918a71cdbe9 1416 #endif
Sergunb 0:8918a71cdbe9 1417 }
Sergunb 0:8918a71cdbe9 1418
Sergunb 0:8918a71cdbe9 1419 //Adjust the length of the multi-part buffer
Sergunb 0:8918a71cdbe9 1420 netBufferSetLength(buffer, offset + length);
Sergunb 0:8918a71cdbe9 1421
Sergunb 0:8918a71cdbe9 1422 //Format IPv6 pseudo header
Sergunb 0:8918a71cdbe9 1423 pseudoHeader.length = htonl(length);
Sergunb 0:8918a71cdbe9 1424 pseudoHeader.reserved = 0;
Sergunb 0:8918a71cdbe9 1425 pseudoHeader.nextHeader = IPV6_ICMPV6_HEADER;
Sergunb 0:8918a71cdbe9 1426
Sergunb 0:8918a71cdbe9 1427 //Calculate ICMPv6 header checksum
Sergunb 0:8918a71cdbe9 1428 message->checksum = ipCalcUpperLayerChecksumEx(&pseudoHeader,
Sergunb 0:8918a71cdbe9 1429 sizeof(Ipv6PseudoHeader), buffer, offset, length);
Sergunb 0:8918a71cdbe9 1430
Sergunb 0:8918a71cdbe9 1431 //Debug message
Sergunb 0:8918a71cdbe9 1432 TRACE_INFO("Sending Router Solicitation message (%" PRIuSIZE " bytes)...\r\n", length);
Sergunb 0:8918a71cdbe9 1433 //Dump message contents for debugging purpose
Sergunb 0:8918a71cdbe9 1434 ndpDumpRouterSolMessage(message);
Sergunb 0:8918a71cdbe9 1435
Sergunb 0:8918a71cdbe9 1436 //Send Router Solicitation message
Sergunb 0:8918a71cdbe9 1437 error = ipv6SendDatagram(interface, &pseudoHeader, buffer, offset, NDP_HOP_LIMIT);
Sergunb 0:8918a71cdbe9 1438
Sergunb 0:8918a71cdbe9 1439 //Free previously allocated memory
Sergunb 0:8918a71cdbe9 1440 netBufferFree(buffer);
Sergunb 0:8918a71cdbe9 1441 //Return status code
Sergunb 0:8918a71cdbe9 1442 return error;
Sergunb 0:8918a71cdbe9 1443 }
Sergunb 0:8918a71cdbe9 1444
Sergunb 0:8918a71cdbe9 1445
Sergunb 0:8918a71cdbe9 1446 /**
Sergunb 0:8918a71cdbe9 1447 * @brief Send a Neighbor Solicitation message
Sergunb 0:8918a71cdbe9 1448 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 1449 * @param[in] targetIpAddr Target IPv6 address
Sergunb 0:8918a71cdbe9 1450 * @param[in] multicast Unicast or unicast Neighbor Solicitation message
Sergunb 0:8918a71cdbe9 1451 * @return Error code
Sergunb 0:8918a71cdbe9 1452 **/
Sergunb 0:8918a71cdbe9 1453
Sergunb 0:8918a71cdbe9 1454 error_t ndpSendNeighborSol(NetInterface *interface,
Sergunb 0:8918a71cdbe9 1455 const Ipv6Addr *targetIpAddr, bool_t multicast)
Sergunb 0:8918a71cdbe9 1456 {
Sergunb 0:8918a71cdbe9 1457 error_t error;
Sergunb 0:8918a71cdbe9 1458 size_t offset;
Sergunb 0:8918a71cdbe9 1459 size_t length;
Sergunb 0:8918a71cdbe9 1460 NetBuffer *buffer;
Sergunb 0:8918a71cdbe9 1461 NdpNeighborSolMessage *message;
Sergunb 0:8918a71cdbe9 1462 Ipv6PseudoHeader pseudoHeader;
Sergunb 0:8918a71cdbe9 1463
Sergunb 0:8918a71cdbe9 1464 //Multicast Neighbor Solicitation message?
Sergunb 0:8918a71cdbe9 1465 if(multicast)
Sergunb 0:8918a71cdbe9 1466 {
Sergunb 0:8918a71cdbe9 1467 //Compute the solicited-node multicast address that
Sergunb 0:8918a71cdbe9 1468 //corresponds to the target IPv6 address
Sergunb 0:8918a71cdbe9 1469 ipv6ComputeSolicitedNodeAddr(targetIpAddr, &pseudoHeader.destAddr);
Sergunb 0:8918a71cdbe9 1470 }
Sergunb 0:8918a71cdbe9 1471 else
Sergunb 0:8918a71cdbe9 1472 {
Sergunb 0:8918a71cdbe9 1473 //Unicast Neighbor Solicitation message
Sergunb 0:8918a71cdbe9 1474 pseudoHeader.destAddr = *targetIpAddr;
Sergunb 0:8918a71cdbe9 1475 }
Sergunb 0:8918a71cdbe9 1476
Sergunb 0:8918a71cdbe9 1477 //Check whether the target address is a tentative address
Sergunb 0:8918a71cdbe9 1478 if(ipv6IsTentativeAddr(interface, targetIpAddr))
Sergunb 0:8918a71cdbe9 1479 {
Sergunb 0:8918a71cdbe9 1480 //The IPv6 source is set to the unspecified address
Sergunb 0:8918a71cdbe9 1481 pseudoHeader.srcAddr = IPV6_UNSPECIFIED_ADDR;
Sergunb 0:8918a71cdbe9 1482 }
Sergunb 0:8918a71cdbe9 1483 else
Sergunb 0:8918a71cdbe9 1484 {
Sergunb 0:8918a71cdbe9 1485 //Select the most appropriate source address to be used
Sergunb 0:8918a71cdbe9 1486 //when sending the Neighbor Solicitation message
Sergunb 0:8918a71cdbe9 1487 error = ipv6SelectSourceAddr(&interface,
Sergunb 0:8918a71cdbe9 1488 targetIpAddr, &pseudoHeader.srcAddr);
Sergunb 0:8918a71cdbe9 1489
Sergunb 0:8918a71cdbe9 1490 //No address assigned to the interface?
Sergunb 0:8918a71cdbe9 1491 if(error)
Sergunb 0:8918a71cdbe9 1492 return error;
Sergunb 0:8918a71cdbe9 1493 }
Sergunb 0:8918a71cdbe9 1494
Sergunb 0:8918a71cdbe9 1495 //The only defined option that may appear in a Neighbor Solicitation
Sergunb 0:8918a71cdbe9 1496 //message is the Source Link-Layer Address option
Sergunb 0:8918a71cdbe9 1497 length = sizeof(NdpNeighborSolMessage) + sizeof(NdpLinkLayerAddrOption);
Sergunb 0:8918a71cdbe9 1498
Sergunb 0:8918a71cdbe9 1499 //Allocate a memory buffer to hold the Neighbor Solicitation message
Sergunb 0:8918a71cdbe9 1500 buffer = ipAllocBuffer(length, &offset);
Sergunb 0:8918a71cdbe9 1501 //Failed to allocate memory?
Sergunb 0:8918a71cdbe9 1502 if(buffer == NULL)
Sergunb 0:8918a71cdbe9 1503 return ERROR_OUT_OF_MEMORY;
Sergunb 0:8918a71cdbe9 1504
Sergunb 0:8918a71cdbe9 1505 //Point to the beginning of the message
Sergunb 0:8918a71cdbe9 1506 message = netBufferAt(buffer, offset);
Sergunb 0:8918a71cdbe9 1507
Sergunb 0:8918a71cdbe9 1508 //Format Neighbor Solicitation message
Sergunb 0:8918a71cdbe9 1509 message->type = ICMPV6_TYPE_NEIGHBOR_SOL;
Sergunb 0:8918a71cdbe9 1510 message->code = 0;
Sergunb 0:8918a71cdbe9 1511 message->checksum = 0;
Sergunb 0:8918a71cdbe9 1512 message->reserved = 0;
Sergunb 0:8918a71cdbe9 1513 message->targetAddr = *targetIpAddr;
Sergunb 0:8918a71cdbe9 1514
Sergunb 0:8918a71cdbe9 1515 //Length of the message, excluding any option
Sergunb 0:8918a71cdbe9 1516 length = sizeof(NdpNeighborSolMessage);
Sergunb 0:8918a71cdbe9 1517
Sergunb 0:8918a71cdbe9 1518 //The Source Link-Layer Address option must not be included
Sergunb 0:8918a71cdbe9 1519 //when the source IPv6 address is the unspecified address
Sergunb 0:8918a71cdbe9 1520 if(!ipv6CompAddr(&pseudoHeader.srcAddr, &IPV6_UNSPECIFIED_ADDR))
Sergunb 0:8918a71cdbe9 1521 {
Sergunb 0:8918a71cdbe9 1522 #if (ETH_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 1523 //Add Source Link-Layer Address option
Sergunb 0:8918a71cdbe9 1524 ndpAddOption(message, &length, NDP_OPT_SOURCE_LINK_LAYER_ADDR,
Sergunb 0:8918a71cdbe9 1525 &interface->macAddr, sizeof(MacAddr));
Sergunb 0:8918a71cdbe9 1526 #endif
Sergunb 0:8918a71cdbe9 1527 }
Sergunb 0:8918a71cdbe9 1528
Sergunb 0:8918a71cdbe9 1529 //Adjust the length of the multi-part buffer
Sergunb 0:8918a71cdbe9 1530 netBufferSetLength(buffer, offset + length);
Sergunb 0:8918a71cdbe9 1531
Sergunb 0:8918a71cdbe9 1532 //Format IPv6 pseudo header
Sergunb 0:8918a71cdbe9 1533 pseudoHeader.length = htonl(length);
Sergunb 0:8918a71cdbe9 1534 pseudoHeader.reserved = 0;
Sergunb 0:8918a71cdbe9 1535 pseudoHeader.nextHeader = IPV6_ICMPV6_HEADER;
Sergunb 0:8918a71cdbe9 1536
Sergunb 0:8918a71cdbe9 1537 //Calculate ICMPv6 header checksum
Sergunb 0:8918a71cdbe9 1538 message->checksum = ipCalcUpperLayerChecksumEx(&pseudoHeader,
Sergunb 0:8918a71cdbe9 1539 sizeof(Ipv6PseudoHeader), buffer, offset, length);
Sergunb 0:8918a71cdbe9 1540
Sergunb 0:8918a71cdbe9 1541 //Debug message
Sergunb 0:8918a71cdbe9 1542 TRACE_INFO("Sending Neighbor Solicitation message (%" PRIuSIZE " bytes)...\r\n", length);
Sergunb 0:8918a71cdbe9 1543 //Dump message contents for debugging purpose
Sergunb 0:8918a71cdbe9 1544 ndpDumpNeighborSolMessage(message);
Sergunb 0:8918a71cdbe9 1545
Sergunb 0:8918a71cdbe9 1546 //Send Neighbor Solicitation message
Sergunb 0:8918a71cdbe9 1547 error = ipv6SendDatagram(interface, &pseudoHeader, buffer, offset, NDP_HOP_LIMIT);
Sergunb 0:8918a71cdbe9 1548
Sergunb 0:8918a71cdbe9 1549 //Free previously allocated memory
Sergunb 0:8918a71cdbe9 1550 netBufferFree(buffer);
Sergunb 0:8918a71cdbe9 1551 //Return status code
Sergunb 0:8918a71cdbe9 1552 return error;
Sergunb 0:8918a71cdbe9 1553 }
Sergunb 0:8918a71cdbe9 1554
Sergunb 0:8918a71cdbe9 1555
Sergunb 0:8918a71cdbe9 1556 /**
Sergunb 0:8918a71cdbe9 1557 * @brief Send a Neighbor Advertisement message
Sergunb 0:8918a71cdbe9 1558 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 1559 * @param[in] targetIpAddr Target IPv6 address
Sergunb 0:8918a71cdbe9 1560 * @param[in] destIpAddr Destination IPv6 address
Sergunb 0:8918a71cdbe9 1561 * @return Error code
Sergunb 0:8918a71cdbe9 1562 **/
Sergunb 0:8918a71cdbe9 1563
Sergunb 0:8918a71cdbe9 1564 error_t ndpSendNeighborAdv(NetInterface *interface,
Sergunb 0:8918a71cdbe9 1565 const Ipv6Addr *targetIpAddr, const Ipv6Addr *destIpAddr)
Sergunb 0:8918a71cdbe9 1566 {
Sergunb 0:8918a71cdbe9 1567 error_t error;
Sergunb 0:8918a71cdbe9 1568 size_t offset;
Sergunb 0:8918a71cdbe9 1569 size_t length;
Sergunb 0:8918a71cdbe9 1570 NetBuffer *buffer;
Sergunb 0:8918a71cdbe9 1571 NdpNeighborAdvMessage *message;
Sergunb 0:8918a71cdbe9 1572 Ipv6PseudoHeader pseudoHeader;
Sergunb 0:8918a71cdbe9 1573
Sergunb 0:8918a71cdbe9 1574 //Destination IP address is the unspecified address?
Sergunb 0:8918a71cdbe9 1575 if(ipv6CompAddr(destIpAddr, &IPV6_UNSPECIFIED_ADDR))
Sergunb 0:8918a71cdbe9 1576 {
Sergunb 0:8918a71cdbe9 1577 //If the destination is the unspecified address, the node must
Sergunb 0:8918a71cdbe9 1578 //multicast the advertisement to the all-nodes address
Sergunb 0:8918a71cdbe9 1579 pseudoHeader.destAddr = IPV6_LINK_LOCAL_ALL_NODES_ADDR;
Sergunb 0:8918a71cdbe9 1580 }
Sergunb 0:8918a71cdbe9 1581 else
Sergunb 0:8918a71cdbe9 1582 {
Sergunb 0:8918a71cdbe9 1583 //Otherwise, the node must unicast the advertisement to
Sergunb 0:8918a71cdbe9 1584 //the destination IP address
Sergunb 0:8918a71cdbe9 1585 pseudoHeader.destAddr = *destIpAddr;
Sergunb 0:8918a71cdbe9 1586 }
Sergunb 0:8918a71cdbe9 1587
Sergunb 0:8918a71cdbe9 1588 //Check whether the target address is a valid anycast address
Sergunb 0:8918a71cdbe9 1589 //assigned to the interface
Sergunb 0:8918a71cdbe9 1590 if(ipv6IsAnycastAddr(interface, targetIpAddr))
Sergunb 0:8918a71cdbe9 1591 {
Sergunb 0:8918a71cdbe9 1592 //Select the most appropriate source address to be used
Sergunb 0:8918a71cdbe9 1593 //when sending the Neighbor Advertisement message
Sergunb 0:8918a71cdbe9 1594 error = ipv6SelectSourceAddr(&interface,
Sergunb 0:8918a71cdbe9 1595 targetIpAddr, &pseudoHeader.srcAddr);
Sergunb 0:8918a71cdbe9 1596
Sergunb 0:8918a71cdbe9 1597 //No address assigned to the interface?
Sergunb 0:8918a71cdbe9 1598 if(error)
Sergunb 0:8918a71cdbe9 1599 return error;
Sergunb 0:8918a71cdbe9 1600 }
Sergunb 0:8918a71cdbe9 1601 else
Sergunb 0:8918a71cdbe9 1602 {
Sergunb 0:8918a71cdbe9 1603 //Set the source IP address
Sergunb 0:8918a71cdbe9 1604 pseudoHeader.srcAddr = *targetIpAddr;
Sergunb 0:8918a71cdbe9 1605 }
Sergunb 0:8918a71cdbe9 1606
Sergunb 0:8918a71cdbe9 1607 //The only defined option that may appear in a Neighbor Advertisement
Sergunb 0:8918a71cdbe9 1608 //message is the Target Link-Layer Address option
Sergunb 0:8918a71cdbe9 1609 length = sizeof(NdpNeighborAdvMessage) + sizeof(NdpLinkLayerAddrOption);
Sergunb 0:8918a71cdbe9 1610
Sergunb 0:8918a71cdbe9 1611 //Allocate a memory buffer to hold the Neighbor Advertisement message
Sergunb 0:8918a71cdbe9 1612 buffer = ipAllocBuffer(length, &offset);
Sergunb 0:8918a71cdbe9 1613 //Failed to allocate memory?
Sergunb 0:8918a71cdbe9 1614 if(buffer == NULL)
Sergunb 0:8918a71cdbe9 1615 return ERROR_OUT_OF_MEMORY;
Sergunb 0:8918a71cdbe9 1616
Sergunb 0:8918a71cdbe9 1617 //Point to the beginning of the message
Sergunb 0:8918a71cdbe9 1618 message = netBufferAt(buffer, offset);
Sergunb 0:8918a71cdbe9 1619
Sergunb 0:8918a71cdbe9 1620 //Format Neighbor Advertisement message
Sergunb 0:8918a71cdbe9 1621 message->type = ICMPV6_TYPE_NEIGHBOR_ADV;
Sergunb 0:8918a71cdbe9 1622 message->code = 0;
Sergunb 0:8918a71cdbe9 1623 message->checksum = 0;
Sergunb 0:8918a71cdbe9 1624 message->reserved1 = 0;
Sergunb 0:8918a71cdbe9 1625 message->reserved2 = 0;
Sergunb 0:8918a71cdbe9 1626 message->targetAddr = *targetIpAddr;
Sergunb 0:8918a71cdbe9 1627
Sergunb 0:8918a71cdbe9 1628 //The Router flag indicates that the sender is a router
Sergunb 0:8918a71cdbe9 1629 if(interface->ipv6Context.isRouter)
Sergunb 0:8918a71cdbe9 1630 message->r = TRUE;
Sergunb 0:8918a71cdbe9 1631 else
Sergunb 0:8918a71cdbe9 1632 message->r = FALSE;
Sergunb 0:8918a71cdbe9 1633
Sergunb 0:8918a71cdbe9 1634 //If the destination is the unspecified address, the node must set
Sergunb 0:8918a71cdbe9 1635 //the Solicited flag to zero
Sergunb 0:8918a71cdbe9 1636 if(ipv6CompAddr(destIpAddr, &IPV6_UNSPECIFIED_ADDR))
Sergunb 0:8918a71cdbe9 1637 message->s = FALSE;
Sergunb 0:8918a71cdbe9 1638 else
Sergunb 0:8918a71cdbe9 1639 message->s = TRUE;
Sergunb 0:8918a71cdbe9 1640
Sergunb 0:8918a71cdbe9 1641 //The Override flag should not be set in solicited advertisements
Sergunb 0:8918a71cdbe9 1642 //for anycast addresses
Sergunb 0:8918a71cdbe9 1643 if(ipv6IsAnycastAddr(interface, targetIpAddr))
Sergunb 0:8918a71cdbe9 1644 message->o = FALSE;
Sergunb 0:8918a71cdbe9 1645 else
Sergunb 0:8918a71cdbe9 1646 message->o = TRUE;
Sergunb 0:8918a71cdbe9 1647
Sergunb 0:8918a71cdbe9 1648 //Length of the message, excluding any option
Sergunb 0:8918a71cdbe9 1649 length = sizeof(NdpNeighborAdvMessage);
Sergunb 0:8918a71cdbe9 1650
Sergunb 0:8918a71cdbe9 1651 #if (ETH_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 1652 //Add Target Link-Layer Address option
Sergunb 0:8918a71cdbe9 1653 ndpAddOption(message, &length, NDP_OPT_TARGET_LINK_LAYER_ADDR,
Sergunb 0:8918a71cdbe9 1654 &interface->macAddr, sizeof(MacAddr));
Sergunb 0:8918a71cdbe9 1655 #endif
Sergunb 0:8918a71cdbe9 1656
Sergunb 0:8918a71cdbe9 1657 //Adjust the length of the multi-part buffer
Sergunb 0:8918a71cdbe9 1658 netBufferSetLength(buffer, offset + length);
Sergunb 0:8918a71cdbe9 1659
Sergunb 0:8918a71cdbe9 1660 //Format IPv6 pseudo header
Sergunb 0:8918a71cdbe9 1661 pseudoHeader.length = htonl(length);
Sergunb 0:8918a71cdbe9 1662 pseudoHeader.reserved = 0;
Sergunb 0:8918a71cdbe9 1663 pseudoHeader.nextHeader = IPV6_ICMPV6_HEADER;
Sergunb 0:8918a71cdbe9 1664
Sergunb 0:8918a71cdbe9 1665 //Calculate ICMPv6 header checksum
Sergunb 0:8918a71cdbe9 1666 message->checksum = ipCalcUpperLayerChecksumEx(&pseudoHeader,
Sergunb 0:8918a71cdbe9 1667 sizeof(Ipv6PseudoHeader), buffer, offset, length);
Sergunb 0:8918a71cdbe9 1668
Sergunb 0:8918a71cdbe9 1669 //Debug message
Sergunb 0:8918a71cdbe9 1670 TRACE_INFO("Sending Neighbor Advertisement message (%" PRIuSIZE " bytes)...\r\n", length);
Sergunb 0:8918a71cdbe9 1671 //Dump message contents for debugging purpose
Sergunb 0:8918a71cdbe9 1672 ndpDumpNeighborAdvMessage(message);
Sergunb 0:8918a71cdbe9 1673
Sergunb 0:8918a71cdbe9 1674 //Send Neighbor Advertisement message
Sergunb 0:8918a71cdbe9 1675 error = ipv6SendDatagram(interface, &pseudoHeader, buffer, offset, NDP_HOP_LIMIT);
Sergunb 0:8918a71cdbe9 1676
Sergunb 0:8918a71cdbe9 1677 //Free previously allocated memory
Sergunb 0:8918a71cdbe9 1678 netBufferFree(buffer);
Sergunb 0:8918a71cdbe9 1679 //Return status code
Sergunb 0:8918a71cdbe9 1680 return error;
Sergunb 0:8918a71cdbe9 1681 }
Sergunb 0:8918a71cdbe9 1682
Sergunb 0:8918a71cdbe9 1683
Sergunb 0:8918a71cdbe9 1684 /**
Sergunb 0:8918a71cdbe9 1685 * @brief Send a Redirect message
Sergunb 0:8918a71cdbe9 1686 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 1687 * @param[in] targetAddr IPv6 address that is a better first hop to use
Sergunb 0:8918a71cdbe9 1688 * for the destination address
Sergunb 0:8918a71cdbe9 1689 * @param[in] ipPacket Multi-part buffer that holds the IPv6 packet that
Sergunb 0:8918a71cdbe9 1690 * triggered the sending of the Redirect
Sergunb 0:8918a71cdbe9 1691 * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet
Sergunb 0:8918a71cdbe9 1692 * @return Error code
Sergunb 0:8918a71cdbe9 1693 **/
Sergunb 0:8918a71cdbe9 1694
Sergunb 0:8918a71cdbe9 1695 error_t ndpSendRedirect(NetInterface *interface, const Ipv6Addr *targetAddr,
Sergunb 0:8918a71cdbe9 1696 const NetBuffer *ipPacket, size_t ipPacketOffset)
Sergunb 0:8918a71cdbe9 1697 {
Sergunb 0:8918a71cdbe9 1698 error_t error;
Sergunb 0:8918a71cdbe9 1699 size_t offset;
Sergunb 0:8918a71cdbe9 1700 size_t length;
Sergunb 0:8918a71cdbe9 1701 size_t ipPacketLength;
Sergunb 0:8918a71cdbe9 1702 size_t optionLength;
Sergunb 0:8918a71cdbe9 1703 size_t paddingLength;
Sergunb 0:8918a71cdbe9 1704 NetBuffer *buffer;
Sergunb 0:8918a71cdbe9 1705 NdpRedirectMessage *message;
Sergunb 0:8918a71cdbe9 1706 NdpRedirectedHeaderOption *option;
Sergunb 0:8918a71cdbe9 1707 NdpNeighborCacheEntry *entry;
Sergunb 0:8918a71cdbe9 1708 Ipv6Header *ipHeader;
Sergunb 0:8918a71cdbe9 1709 Ipv6PseudoHeader pseudoHeader;
Sergunb 0:8918a71cdbe9 1710 uint8_t padding[8];
Sergunb 0:8918a71cdbe9 1711
Sergunb 0:8918a71cdbe9 1712 //Retrieve the length of the forwarded IPv6 packet
Sergunb 0:8918a71cdbe9 1713 ipPacketLength = netBufferGetLength(ipPacket) - ipPacketOffset;
Sergunb 0:8918a71cdbe9 1714
Sergunb 0:8918a71cdbe9 1715 //Check the length of the IPv6 packet
Sergunb 0:8918a71cdbe9 1716 if(ipPacketLength < sizeof(Ipv6Header))
Sergunb 0:8918a71cdbe9 1717 return ERROR_INVALID_LENGTH;
Sergunb 0:8918a71cdbe9 1718
Sergunb 0:8918a71cdbe9 1719 //Point to the header of the invoking packet
Sergunb 0:8918a71cdbe9 1720 ipHeader = netBufferAt(ipPacket, ipPacketOffset);
Sergunb 0:8918a71cdbe9 1721 //Sanity check
Sergunb 0:8918a71cdbe9 1722 if(ipHeader == NULL)
Sergunb 0:8918a71cdbe9 1723 return ERROR_FAILURE;
Sergunb 0:8918a71cdbe9 1724
Sergunb 0:8918a71cdbe9 1725 //The only defined options that may appear in a Redirect message are the
Sergunb 0:8918a71cdbe9 1726 //Target Link-Layer Address option and the Redirected Header option
Sergunb 0:8918a71cdbe9 1727 length = sizeof(NdpRedirectMessage) + sizeof(NdpLinkLayerAddrOption) +
Sergunb 0:8918a71cdbe9 1728 sizeof(NdpRedirectedHeaderOption);
Sergunb 0:8918a71cdbe9 1729
Sergunb 0:8918a71cdbe9 1730 //Allocate a memory buffer to hold the Redirect message
Sergunb 0:8918a71cdbe9 1731 buffer = ipAllocBuffer(length, &offset);
Sergunb 0:8918a71cdbe9 1732 //Failed to allocate memory?
Sergunb 0:8918a71cdbe9 1733 if(buffer == NULL)
Sergunb 0:8918a71cdbe9 1734 return ERROR_OUT_OF_MEMORY;
Sergunb 0:8918a71cdbe9 1735
Sergunb 0:8918a71cdbe9 1736 //Point to the beginning of the message
Sergunb 0:8918a71cdbe9 1737 message = netBufferAt(buffer, offset);
Sergunb 0:8918a71cdbe9 1738
Sergunb 0:8918a71cdbe9 1739 //Format Redirect message
Sergunb 0:8918a71cdbe9 1740 message->type = ICMPV6_TYPE_REDIRECT;
Sergunb 0:8918a71cdbe9 1741 message->code = 0;
Sergunb 0:8918a71cdbe9 1742 message->checksum = 0;
Sergunb 0:8918a71cdbe9 1743 message->reserved = 0;
Sergunb 0:8918a71cdbe9 1744 message->targetAddr = *targetAddr;
Sergunb 0:8918a71cdbe9 1745 message->destAddr = ipHeader->destAddr;
Sergunb 0:8918a71cdbe9 1746
Sergunb 0:8918a71cdbe9 1747 //Length of the message, excluding any option
Sergunb 0:8918a71cdbe9 1748 length = sizeof(NdpRedirectMessage);
Sergunb 0:8918a71cdbe9 1749
Sergunb 0:8918a71cdbe9 1750 //Search the Neighbor cache for the specified target address
Sergunb 0:8918a71cdbe9 1751 entry = ndpFindNeighborCacheEntry(interface, targetAddr);
Sergunb 0:8918a71cdbe9 1752
Sergunb 0:8918a71cdbe9 1753 //Include the link-layer address of the target, if known
Sergunb 0:8918a71cdbe9 1754 if(entry != NULL)
Sergunb 0:8918a71cdbe9 1755 {
Sergunb 0:8918a71cdbe9 1756 //Add Target Link-Layer Address option
Sergunb 0:8918a71cdbe9 1757 ndpAddOption(message, &length, NDP_OPT_TARGET_LINK_LAYER_ADDR,
Sergunb 0:8918a71cdbe9 1758 &entry->macAddr, sizeof(MacAddr));
Sergunb 0:8918a71cdbe9 1759 }
Sergunb 0:8918a71cdbe9 1760
Sergunb 0:8918a71cdbe9 1761 //Retrieve the length of the IPv6 packet that triggered the sending
Sergunb 0:8918a71cdbe9 1762 //of the Redirect
Sergunb 0:8918a71cdbe9 1763 ipPacketLength = netBufferGetLength(ipPacket) - ipPacketOffset;
Sergunb 0:8918a71cdbe9 1764
Sergunb 0:8918a71cdbe9 1765 //Return as much of the forwarded IPv6 packet as can fit without
Sergunb 0:8918a71cdbe9 1766 //the redirect packet exceeding the minimum IPv6 MTU
Sergunb 0:8918a71cdbe9 1767 ipPacketLength = MIN(ipPacketLength, IPV6_DEFAULT_MTU -
Sergunb 0:8918a71cdbe9 1768 sizeof(NdpRedirectedHeaderOption) - length);
Sergunb 0:8918a71cdbe9 1769
Sergunb 0:8918a71cdbe9 1770 //Length of the Redirected Header option in units of 8 bytes including
Sergunb 0:8918a71cdbe9 1771 //the type and length fields
Sergunb 0:8918a71cdbe9 1772 optionLength = (ipPacketLength + sizeof(NdpOption) + 7) / 8;
Sergunb 0:8918a71cdbe9 1773
Sergunb 0:8918a71cdbe9 1774 //Add Redirected Header option
Sergunb 0:8918a71cdbe9 1775 option = (NdpRedirectedHeaderOption *) ((uint8_t *) message + length);
Sergunb 0:8918a71cdbe9 1776
Sergunb 0:8918a71cdbe9 1777 //Format Redirected Header option
Sergunb 0:8918a71cdbe9 1778 option->type = NDP_OPT_REDIRECTED_HEADER;
Sergunb 0:8918a71cdbe9 1779 option->length = (uint8_t) optionLength;
Sergunb 0:8918a71cdbe9 1780 option->reserved1 = 0;
Sergunb 0:8918a71cdbe9 1781 option->reserved2 = 0;
Sergunb 0:8918a71cdbe9 1782
Sergunb 0:8918a71cdbe9 1783 //Update the length of Redirect message
Sergunb 0:8918a71cdbe9 1784 length += sizeof(NdpRedirectedHeaderOption);
Sergunb 0:8918a71cdbe9 1785
Sergunb 0:8918a71cdbe9 1786 //Adjust the length of the multi-part buffer
Sergunb 0:8918a71cdbe9 1787 netBufferSetLength(buffer, offset + length);
Sergunb 0:8918a71cdbe9 1788
Sergunb 0:8918a71cdbe9 1789 //Copy the contents of the forwarded IPv6 packet
Sergunb 0:8918a71cdbe9 1790 error = netBufferConcat(buffer, ipPacket, ipPacketOffset, ipPacketLength);
Sergunb 0:8918a71cdbe9 1791
Sergunb 0:8918a71cdbe9 1792 //Check status code
Sergunb 0:8918a71cdbe9 1793 if(!error)
Sergunb 0:8918a71cdbe9 1794 {
Sergunb 0:8918a71cdbe9 1795 //Options should be padded when necessary to ensure that they end on
Sergunb 0:8918a71cdbe9 1796 //their natural 64-bit boundaries
Sergunb 0:8918a71cdbe9 1797 if((ipPacketLength + sizeof(NdpRedirectedHeaderOption)) < (optionLength * 8))
Sergunb 0:8918a71cdbe9 1798 {
Sergunb 0:8918a71cdbe9 1799 //Determine the amount of padding data to append
Sergunb 0:8918a71cdbe9 1800 paddingLength = (optionLength * 8) - ipPacketLength -
Sergunb 0:8918a71cdbe9 1801 sizeof(NdpRedirectedHeaderOption);
Sergunb 0:8918a71cdbe9 1802
Sergunb 0:8918a71cdbe9 1803 //Prepare padding data
Sergunb 0:8918a71cdbe9 1804 memset(padding, 0, paddingLength);
Sergunb 0:8918a71cdbe9 1805 //Append padding bytes
Sergunb 0:8918a71cdbe9 1806 error = netBufferAppend(buffer, padding, paddingLength);
Sergunb 0:8918a71cdbe9 1807 }
Sergunb 0:8918a71cdbe9 1808 }
Sergunb 0:8918a71cdbe9 1809
Sergunb 0:8918a71cdbe9 1810 //Check status code
Sergunb 0:8918a71cdbe9 1811 if(!error)
Sergunb 0:8918a71cdbe9 1812 {
Sergunb 0:8918a71cdbe9 1813 //Get the length of the resulting message
Sergunb 0:8918a71cdbe9 1814 length = netBufferGetLength(buffer) - offset;
Sergunb 0:8918a71cdbe9 1815
Sergunb 0:8918a71cdbe9 1816 //Format IPv6 pseudo header
Sergunb 0:8918a71cdbe9 1817 pseudoHeader.srcAddr = interface->ipv6Context.addrList[0].addr;
Sergunb 0:8918a71cdbe9 1818 pseudoHeader.destAddr = ipHeader->srcAddr;
Sergunb 0:8918a71cdbe9 1819 pseudoHeader.length = htonl(length);
Sergunb 0:8918a71cdbe9 1820 pseudoHeader.reserved = 0;
Sergunb 0:8918a71cdbe9 1821 pseudoHeader.nextHeader = IPV6_ICMPV6_HEADER;
Sergunb 0:8918a71cdbe9 1822
Sergunb 0:8918a71cdbe9 1823 //Message checksum calculation
Sergunb 0:8918a71cdbe9 1824 message->checksum = ipCalcUpperLayerChecksumEx(&pseudoHeader,
Sergunb 0:8918a71cdbe9 1825 sizeof(Ipv6PseudoHeader), buffer, offset, length);
Sergunb 0:8918a71cdbe9 1826
Sergunb 0:8918a71cdbe9 1827 //Debug message
Sergunb 0:8918a71cdbe9 1828 TRACE_INFO("Sending Redirect message (%" PRIuSIZE " bytes)...\r\n", length);
Sergunb 0:8918a71cdbe9 1829 //Dump message contents for debugging purpose
Sergunb 0:8918a71cdbe9 1830 ndpDumpRedirectMessage(message);
Sergunb 0:8918a71cdbe9 1831
Sergunb 0:8918a71cdbe9 1832 //Send Redirect message
Sergunb 0:8918a71cdbe9 1833 error = ipv6SendDatagram(interface, &pseudoHeader, buffer, offset, NDP_HOP_LIMIT);
Sergunb 0:8918a71cdbe9 1834 }
Sergunb 0:8918a71cdbe9 1835
Sergunb 0:8918a71cdbe9 1836 //Free previously allocated memory
Sergunb 0:8918a71cdbe9 1837 netBufferFree(buffer);
Sergunb 0:8918a71cdbe9 1838
Sergunb 0:8918a71cdbe9 1839 //Return status code
Sergunb 0:8918a71cdbe9 1840 return error;
Sergunb 0:8918a71cdbe9 1841 }
Sergunb 0:8918a71cdbe9 1842
Sergunb 0:8918a71cdbe9 1843
Sergunb 0:8918a71cdbe9 1844 /**
Sergunb 0:8918a71cdbe9 1845 * @brief Dump Router Solicitation message for debugging purpose
Sergunb 0:8918a71cdbe9 1846 * @param[in] message Router Solicitation message
Sergunb 0:8918a71cdbe9 1847 **/
Sergunb 0:8918a71cdbe9 1848
Sergunb 0:8918a71cdbe9 1849 void ndpDumpRouterSolMessage(const NdpRouterSolMessage *message)
Sergunb 0:8918a71cdbe9 1850 {
Sergunb 0:8918a71cdbe9 1851 //Dump Router Solicitation message
Sergunb 0:8918a71cdbe9 1852 TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
Sergunb 0:8918a71cdbe9 1853 TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
Sergunb 0:8918a71cdbe9 1854 TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
Sergunb 0:8918a71cdbe9 1855 }
Sergunb 0:8918a71cdbe9 1856
Sergunb 0:8918a71cdbe9 1857
Sergunb 0:8918a71cdbe9 1858 /**
Sergunb 0:8918a71cdbe9 1859 * @brief Dump Router Advertisement message for debugging purpose
Sergunb 0:8918a71cdbe9 1860 * @param[in] message Router Advertisement message
Sergunb 0:8918a71cdbe9 1861 **/
Sergunb 0:8918a71cdbe9 1862
Sergunb 0:8918a71cdbe9 1863 void ndpDumpRouterAdvMessage(const NdpRouterAdvMessage *message)
Sergunb 0:8918a71cdbe9 1864 {
Sergunb 0:8918a71cdbe9 1865 //Dump Router Advertisement message
Sergunb 0:8918a71cdbe9 1866 TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
Sergunb 0:8918a71cdbe9 1867 TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
Sergunb 0:8918a71cdbe9 1868 TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
Sergunb 0:8918a71cdbe9 1869 TRACE_DEBUG(" Cur Hop Limit = %" PRIu8 "\r\n", message->curHopLimit);
Sergunb 0:8918a71cdbe9 1870 TRACE_DEBUG(" M = %" PRIu8 "\r\n", message->m);
Sergunb 0:8918a71cdbe9 1871 TRACE_DEBUG(" O = %" PRIu8 "\r\n", message->o);
Sergunb 0:8918a71cdbe9 1872 TRACE_DEBUG(" Router Lifetime = %" PRIu16 "\r\n", ntohs(message->routerLifetime));
Sergunb 0:8918a71cdbe9 1873 TRACE_DEBUG(" Reachable Time = %" PRIu32 "\r\n", ntohl(message->reachableTime));
Sergunb 0:8918a71cdbe9 1874 TRACE_DEBUG(" Retrans Timer = %" PRIu32 "\r\n", ntohl(message->retransTimer));
Sergunb 0:8918a71cdbe9 1875 }
Sergunb 0:8918a71cdbe9 1876
Sergunb 0:8918a71cdbe9 1877
Sergunb 0:8918a71cdbe9 1878 /**
Sergunb 0:8918a71cdbe9 1879 * @brief Dump Neighbor Solicitation message for debugging purpose
Sergunb 0:8918a71cdbe9 1880 * @param[in] message Neighbor Solicitation message
Sergunb 0:8918a71cdbe9 1881 **/
Sergunb 0:8918a71cdbe9 1882
Sergunb 0:8918a71cdbe9 1883 void ndpDumpNeighborSolMessage(const NdpNeighborSolMessage *message)
Sergunb 0:8918a71cdbe9 1884 {
Sergunb 0:8918a71cdbe9 1885 //Dump Neighbor Solicitation message
Sergunb 0:8918a71cdbe9 1886 TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
Sergunb 0:8918a71cdbe9 1887 TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
Sergunb 0:8918a71cdbe9 1888 TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
Sergunb 0:8918a71cdbe9 1889 TRACE_DEBUG(" Target Address = %s\r\n", ipv6AddrToString(&message->targetAddr, NULL));
Sergunb 0:8918a71cdbe9 1890 }
Sergunb 0:8918a71cdbe9 1891
Sergunb 0:8918a71cdbe9 1892
Sergunb 0:8918a71cdbe9 1893 /**
Sergunb 0:8918a71cdbe9 1894 * @brief Dump Neighbor Advertisement message for debugging purpose
Sergunb 0:8918a71cdbe9 1895 * @param[in] message Neighbor Advertisement message
Sergunb 0:8918a71cdbe9 1896 **/
Sergunb 0:8918a71cdbe9 1897
Sergunb 0:8918a71cdbe9 1898 void ndpDumpNeighborAdvMessage(const NdpNeighborAdvMessage *message)
Sergunb 0:8918a71cdbe9 1899 {
Sergunb 0:8918a71cdbe9 1900 //Dump Neighbor Advertisement message
Sergunb 0:8918a71cdbe9 1901 TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
Sergunb 0:8918a71cdbe9 1902 TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
Sergunb 0:8918a71cdbe9 1903 TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
Sergunb 0:8918a71cdbe9 1904 TRACE_DEBUG(" R = %" PRIu8 "\r\n", message->r);
Sergunb 0:8918a71cdbe9 1905 TRACE_DEBUG(" S = %" PRIu8 "\r\n", message->s);
Sergunb 0:8918a71cdbe9 1906 TRACE_DEBUG(" O = %" PRIu8 "\r\n", message->o);
Sergunb 0:8918a71cdbe9 1907 TRACE_DEBUG(" Target Address = %s\r\n", ipv6AddrToString(&message->targetAddr, NULL));
Sergunb 0:8918a71cdbe9 1908 }
Sergunb 0:8918a71cdbe9 1909
Sergunb 0:8918a71cdbe9 1910
Sergunb 0:8918a71cdbe9 1911 /**
Sergunb 0:8918a71cdbe9 1912 * @brief Dump Redirect message for debugging purpose
Sergunb 0:8918a71cdbe9 1913 * @param[in] message Redirect message
Sergunb 0:8918a71cdbe9 1914 **/
Sergunb 0:8918a71cdbe9 1915
Sergunb 0:8918a71cdbe9 1916 void ndpDumpRedirectMessage(const NdpRedirectMessage *message)
Sergunb 0:8918a71cdbe9 1917 {
Sergunb 0:8918a71cdbe9 1918 //Dump Neighbor Advertisement message
Sergunb 0:8918a71cdbe9 1919 TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
Sergunb 0:8918a71cdbe9 1920 TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
Sergunb 0:8918a71cdbe9 1921 TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
Sergunb 0:8918a71cdbe9 1922 TRACE_DEBUG(" Target Address = %s\r\n", ipv6AddrToString(&message->targetAddr, NULL));
Sergunb 0:8918a71cdbe9 1923 TRACE_DEBUG(" Destination Address = %s\r\n", ipv6AddrToString(&message->destAddr, NULL));
Sergunb 0:8918a71cdbe9 1924 }
Sergunb 0:8918a71cdbe9 1925
Sergunb 0:8918a71cdbe9 1926 #endif
Sergunb 0:8918a71cdbe9 1927