Webserver+3d print
cyclone_tcp/ipv6/ndp.c@0:8918a71cdbe9, 2017-02-04 (annotated)
- Committer:
- Sergunb
- Date:
- Sat Feb 04 18:15:49 2017 +0000
- Revision:
- 0:8918a71cdbe9
nothing else
Who changed what in which revision?
User | Revision | Line number | New 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 |