Webserver+3d print

Dependents:   Nucleo

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

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sergunb 0:8918a71cdbe9 1 /**
Sergunb 0:8918a71cdbe9 2 * @file arp.c
Sergunb 0:8918a71cdbe9 3 * @brief ARP (Address Resolution 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 * Address Resolution Protocol is used to determine the hardware address of
Sergunb 0:8918a71cdbe9 28 * a specific host when only its IPv4 address is known. Refer to RFC 826
Sergunb 0:8918a71cdbe9 29 *
Sergunb 0:8918a71cdbe9 30 * @author Oryx Embedded SARL (www.oryx-embedded.com)
Sergunb 0:8918a71cdbe9 31 * @version 1.7.6
Sergunb 0:8918a71cdbe9 32 **/
Sergunb 0:8918a71cdbe9 33
Sergunb 0:8918a71cdbe9 34 //Switch to the appropriate trace level
Sergunb 0:8918a71cdbe9 35 #define TRACE_LEVEL ARP_TRACE_LEVEL
Sergunb 0:8918a71cdbe9 36
Sergunb 0:8918a71cdbe9 37 //Dependencies
Sergunb 0:8918a71cdbe9 38 #include <string.h>
Sergunb 0:8918a71cdbe9 39 #include "core/net.h"
Sergunb 0:8918a71cdbe9 40 #include "core/ethernet.h"
Sergunb 0:8918a71cdbe9 41 #include "ipv4/arp.h"
Sergunb 0:8918a71cdbe9 42 #include "debug.h"
Sergunb 0:8918a71cdbe9 43
Sergunb 0:8918a71cdbe9 44 //Check TCP/IP stack configuration
Sergunb 0:8918a71cdbe9 45 #if (IPV4_SUPPORT == ENABLED && ETH_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 46
Sergunb 0:8918a71cdbe9 47 //Tick counter to handle periodic operations
Sergunb 0:8918a71cdbe9 48 systime_t arpTickCounter;
Sergunb 0:8918a71cdbe9 49
Sergunb 0:8918a71cdbe9 50
Sergunb 0:8918a71cdbe9 51 /**
Sergunb 0:8918a71cdbe9 52 * @brief ARP cache initialization
Sergunb 0:8918a71cdbe9 53 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 54 * @return Error code
Sergunb 0:8918a71cdbe9 55 **/
Sergunb 0:8918a71cdbe9 56
Sergunb 0:8918a71cdbe9 57 error_t arpInit(NetInterface *interface)
Sergunb 0:8918a71cdbe9 58 {
Sergunb 0:8918a71cdbe9 59 //Initialize the ARP cache
Sergunb 0:8918a71cdbe9 60 memset(interface->arpCache, 0, sizeof(interface->arpCache));
Sergunb 0:8918a71cdbe9 61
Sergunb 0:8918a71cdbe9 62 //Successful initialization
Sergunb 0:8918a71cdbe9 63 return NO_ERROR;
Sergunb 0:8918a71cdbe9 64 }
Sergunb 0:8918a71cdbe9 65
Sergunb 0:8918a71cdbe9 66
Sergunb 0:8918a71cdbe9 67 /**
Sergunb 0:8918a71cdbe9 68 * @brief Flush ARP cache
Sergunb 0:8918a71cdbe9 69 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 70 **/
Sergunb 0:8918a71cdbe9 71
Sergunb 0:8918a71cdbe9 72 void arpFlushCache(NetInterface *interface)
Sergunb 0:8918a71cdbe9 73 {
Sergunb 0:8918a71cdbe9 74 uint_t i;
Sergunb 0:8918a71cdbe9 75 ArpCacheEntry *entry;
Sergunb 0:8918a71cdbe9 76
Sergunb 0:8918a71cdbe9 77 //Loop through ARP cache entries
Sergunb 0:8918a71cdbe9 78 for(i = 0; i < ARP_CACHE_SIZE; i++)
Sergunb 0:8918a71cdbe9 79 {
Sergunb 0:8918a71cdbe9 80 //Point to the current entry
Sergunb 0:8918a71cdbe9 81 entry = &interface->arpCache[i];
Sergunb 0:8918a71cdbe9 82
Sergunb 0:8918a71cdbe9 83 //Drop packets that are waiting for address resolution
Sergunb 0:8918a71cdbe9 84 arpFlushQueuedPackets(interface, entry);
Sergunb 0:8918a71cdbe9 85 //Release ARP entry
Sergunb 0:8918a71cdbe9 86 entry->state = ARP_STATE_NONE;
Sergunb 0:8918a71cdbe9 87 }
Sergunb 0:8918a71cdbe9 88 }
Sergunb 0:8918a71cdbe9 89
Sergunb 0:8918a71cdbe9 90
Sergunb 0:8918a71cdbe9 91 /**
Sergunb 0:8918a71cdbe9 92 * @brief Create a new entry in the ARP cache
Sergunb 0:8918a71cdbe9 93 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 94 * @return Pointer to the newly created entry
Sergunb 0:8918a71cdbe9 95 **/
Sergunb 0:8918a71cdbe9 96
Sergunb 0:8918a71cdbe9 97 ArpCacheEntry *arpCreateEntry(NetInterface *interface)
Sergunb 0:8918a71cdbe9 98 {
Sergunb 0:8918a71cdbe9 99 uint_t i;
Sergunb 0:8918a71cdbe9 100 ArpCacheEntry *entry;
Sergunb 0:8918a71cdbe9 101 ArpCacheEntry *oldestEntry;
Sergunb 0:8918a71cdbe9 102
Sergunb 0:8918a71cdbe9 103 //Keep track of the oldest entry
Sergunb 0:8918a71cdbe9 104 oldestEntry = &interface->arpCache[0];
Sergunb 0:8918a71cdbe9 105
Sergunb 0:8918a71cdbe9 106 //Loop through ARP cache entries
Sergunb 0:8918a71cdbe9 107 for(i = 0; i < ARP_CACHE_SIZE; i++)
Sergunb 0:8918a71cdbe9 108 {
Sergunb 0:8918a71cdbe9 109 //Point to the current entry
Sergunb 0:8918a71cdbe9 110 entry = &interface->arpCache[i];
Sergunb 0:8918a71cdbe9 111
Sergunb 0:8918a71cdbe9 112 //Check whether the entry is currently in used or not
Sergunb 0:8918a71cdbe9 113 if(entry->state == ARP_STATE_NONE)
Sergunb 0:8918a71cdbe9 114 {
Sergunb 0:8918a71cdbe9 115 //Erase contents
Sergunb 0:8918a71cdbe9 116 memset(entry, 0, sizeof(ArpCacheEntry));
Sergunb 0:8918a71cdbe9 117 //Return a pointer to the ARP entry
Sergunb 0:8918a71cdbe9 118 return entry;
Sergunb 0:8918a71cdbe9 119 }
Sergunb 0:8918a71cdbe9 120
Sergunb 0:8918a71cdbe9 121 //Keep track of the oldest entry in the table
Sergunb 0:8918a71cdbe9 122 if(timeCompare(entry->timestamp, oldestEntry->timestamp) < 0)
Sergunb 0:8918a71cdbe9 123 oldestEntry = entry;
Sergunb 0:8918a71cdbe9 124 }
Sergunb 0:8918a71cdbe9 125
Sergunb 0:8918a71cdbe9 126 //Drop any pending packets
Sergunb 0:8918a71cdbe9 127 arpFlushQueuedPackets(interface, oldestEntry);
Sergunb 0:8918a71cdbe9 128 //The oldest entry is removed whenever the table runs out of space
Sergunb 0:8918a71cdbe9 129 memset(oldestEntry, 0, sizeof(ArpCacheEntry));
Sergunb 0:8918a71cdbe9 130 //Return a pointer to the ARP entry
Sergunb 0:8918a71cdbe9 131 return oldestEntry;
Sergunb 0:8918a71cdbe9 132 }
Sergunb 0:8918a71cdbe9 133
Sergunb 0:8918a71cdbe9 134
Sergunb 0:8918a71cdbe9 135 /**
Sergunb 0:8918a71cdbe9 136 * @brief Search the ARP cache for a given IPv4 address
Sergunb 0:8918a71cdbe9 137 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 138 * @param[in] ipAddr IPv4 address
Sergunb 0:8918a71cdbe9 139 * @return A pointer to the matching ARP entry is returned. NULL is returned
Sergunb 0:8918a71cdbe9 140 * if the specified IPv4 address could not be found in ARP cache
Sergunb 0:8918a71cdbe9 141 **/
Sergunb 0:8918a71cdbe9 142
Sergunb 0:8918a71cdbe9 143 ArpCacheEntry *arpFindEntry(NetInterface *interface, Ipv4Addr ipAddr)
Sergunb 0:8918a71cdbe9 144 {
Sergunb 0:8918a71cdbe9 145 uint_t i;
Sergunb 0:8918a71cdbe9 146 ArpCacheEntry *entry;
Sergunb 0:8918a71cdbe9 147
Sergunb 0:8918a71cdbe9 148 //Loop through ARP cache entries
Sergunb 0:8918a71cdbe9 149 for(i = 0; i < ARP_CACHE_SIZE; i++)
Sergunb 0:8918a71cdbe9 150 {
Sergunb 0:8918a71cdbe9 151 //Point to the current entry
Sergunb 0:8918a71cdbe9 152 entry = &interface->arpCache[i];
Sergunb 0:8918a71cdbe9 153
Sergunb 0:8918a71cdbe9 154 //Check whether the entry is currently in used
Sergunb 0:8918a71cdbe9 155 if(entry->state != ARP_STATE_NONE)
Sergunb 0:8918a71cdbe9 156 {
Sergunb 0:8918a71cdbe9 157 //Current entry matches the specified address?
Sergunb 0:8918a71cdbe9 158 if(entry->ipAddr == ipAddr)
Sergunb 0:8918a71cdbe9 159 return entry;
Sergunb 0:8918a71cdbe9 160 }
Sergunb 0:8918a71cdbe9 161 }
Sergunb 0:8918a71cdbe9 162
Sergunb 0:8918a71cdbe9 163 //No matching entry in ARP cache...
Sergunb 0:8918a71cdbe9 164 return NULL;
Sergunb 0:8918a71cdbe9 165 }
Sergunb 0:8918a71cdbe9 166
Sergunb 0:8918a71cdbe9 167
Sergunb 0:8918a71cdbe9 168 /**
Sergunb 0:8918a71cdbe9 169 * @brief Send packets that are waiting for address resolution
Sergunb 0:8918a71cdbe9 170 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 171 * @param[in] entry Pointer to a ARP cache entry
Sergunb 0:8918a71cdbe9 172 **/
Sergunb 0:8918a71cdbe9 173
Sergunb 0:8918a71cdbe9 174 void arpSendQueuedPackets(NetInterface *interface, ArpCacheEntry *entry)
Sergunb 0:8918a71cdbe9 175 {
Sergunb 0:8918a71cdbe9 176 uint_t i;
Sergunb 0:8918a71cdbe9 177 ArpQueueItem *item;
Sergunb 0:8918a71cdbe9 178
Sergunb 0:8918a71cdbe9 179 //Check current state
Sergunb 0:8918a71cdbe9 180 if(entry->state == ARP_STATE_INCOMPLETE)
Sergunb 0:8918a71cdbe9 181 {
Sergunb 0:8918a71cdbe9 182 //Loop through the queued packets
Sergunb 0:8918a71cdbe9 183 for(i = 0; i < entry->queueSize; i++)
Sergunb 0:8918a71cdbe9 184 {
Sergunb 0:8918a71cdbe9 185 //Point to the current queue item
Sergunb 0:8918a71cdbe9 186 item = &entry->queue[i];
Sergunb 0:8918a71cdbe9 187
Sergunb 0:8918a71cdbe9 188 //Send the IPv4 packet
Sergunb 0:8918a71cdbe9 189 ethSendFrame(interface, &entry->macAddr,
Sergunb 0:8918a71cdbe9 190 item->buffer, item->offset, ETH_TYPE_IPV4);
Sergunb 0:8918a71cdbe9 191
Sergunb 0:8918a71cdbe9 192 //Release memory buffer
Sergunb 0:8918a71cdbe9 193 netBufferFree(item->buffer);
Sergunb 0:8918a71cdbe9 194 }
Sergunb 0:8918a71cdbe9 195 }
Sergunb 0:8918a71cdbe9 196
Sergunb 0:8918a71cdbe9 197 //The queue is now empty
Sergunb 0:8918a71cdbe9 198 entry->queueSize = 0;
Sergunb 0:8918a71cdbe9 199 }
Sergunb 0:8918a71cdbe9 200
Sergunb 0:8918a71cdbe9 201
Sergunb 0:8918a71cdbe9 202 /**
Sergunb 0:8918a71cdbe9 203 * @brief Flush packet queue
Sergunb 0:8918a71cdbe9 204 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 205 * @param[in] entry Pointer to a ARP cache entry
Sergunb 0:8918a71cdbe9 206 **/
Sergunb 0:8918a71cdbe9 207
Sergunb 0:8918a71cdbe9 208 void arpFlushQueuedPackets(NetInterface *interface, ArpCacheEntry *entry)
Sergunb 0:8918a71cdbe9 209 {
Sergunb 0:8918a71cdbe9 210 uint_t i;
Sergunb 0:8918a71cdbe9 211
Sergunb 0:8918a71cdbe9 212 //Check current state
Sergunb 0:8918a71cdbe9 213 if(entry->state == ARP_STATE_INCOMPLETE)
Sergunb 0:8918a71cdbe9 214 {
Sergunb 0:8918a71cdbe9 215 //Drop packets that are waiting for address resolution
Sergunb 0:8918a71cdbe9 216 for(i = 0; i < entry->queueSize; i++)
Sergunb 0:8918a71cdbe9 217 {
Sergunb 0:8918a71cdbe9 218 //Release memory buffer
Sergunb 0:8918a71cdbe9 219 netBufferFree(entry->queue[i].buffer);
Sergunb 0:8918a71cdbe9 220 }
Sergunb 0:8918a71cdbe9 221 }
Sergunb 0:8918a71cdbe9 222
Sergunb 0:8918a71cdbe9 223 //The queue is now empty
Sergunb 0:8918a71cdbe9 224 entry->queueSize = 0;
Sergunb 0:8918a71cdbe9 225 }
Sergunb 0:8918a71cdbe9 226
Sergunb 0:8918a71cdbe9 227
Sergunb 0:8918a71cdbe9 228 /**
Sergunb 0:8918a71cdbe9 229 * @brief Address resolution using ARP protocol
Sergunb 0:8918a71cdbe9 230 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 231 * @param[in] ipAddr IPv4 address
Sergunb 0:8918a71cdbe9 232 * @param[in] macAddr Physical address matching the specified IPv4 address
Sergunb 0:8918a71cdbe9 233 * @return Error code
Sergunb 0:8918a71cdbe9 234 **/
Sergunb 0:8918a71cdbe9 235
Sergunb 0:8918a71cdbe9 236 error_t arpResolve(NetInterface *interface, Ipv4Addr ipAddr, MacAddr *macAddr)
Sergunb 0:8918a71cdbe9 237 {
Sergunb 0:8918a71cdbe9 238 error_t error;
Sergunb 0:8918a71cdbe9 239 ArpCacheEntry *entry;
Sergunb 0:8918a71cdbe9 240
Sergunb 0:8918a71cdbe9 241 //Search the ARP cache for the specified IPv4 address
Sergunb 0:8918a71cdbe9 242 entry = arpFindEntry(interface, ipAddr);
Sergunb 0:8918a71cdbe9 243
Sergunb 0:8918a71cdbe9 244 //Check whether a matching entry has been found
Sergunb 0:8918a71cdbe9 245 if(entry != NULL)
Sergunb 0:8918a71cdbe9 246 {
Sergunb 0:8918a71cdbe9 247 //Check the state of the ARP entry
Sergunb 0:8918a71cdbe9 248 if(entry->state == ARP_STATE_INCOMPLETE)
Sergunb 0:8918a71cdbe9 249 {
Sergunb 0:8918a71cdbe9 250 //The address resolution is already in progress
Sergunb 0:8918a71cdbe9 251 error = ERROR_IN_PROGRESS;
Sergunb 0:8918a71cdbe9 252 }
Sergunb 0:8918a71cdbe9 253 else if(entry->state == ARP_STATE_STALE)
Sergunb 0:8918a71cdbe9 254 {
Sergunb 0:8918a71cdbe9 255 //Copy the MAC address associated with the specified IPv4 address
Sergunb 0:8918a71cdbe9 256 *macAddr = entry->macAddr;
Sergunb 0:8918a71cdbe9 257
Sergunb 0:8918a71cdbe9 258 //Start delay timer
Sergunb 0:8918a71cdbe9 259 entry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 260 //Delay before sending the first probe
Sergunb 0:8918a71cdbe9 261 entry->timeout = ARP_DELAY_FIRST_PROBE_TIME;
Sergunb 0:8918a71cdbe9 262 //Switch to the DELAY state
Sergunb 0:8918a71cdbe9 263 entry->state = ARP_STATE_DELAY;
Sergunb 0:8918a71cdbe9 264
Sergunb 0:8918a71cdbe9 265 //Successful address resolution
Sergunb 0:8918a71cdbe9 266 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 267 }
Sergunb 0:8918a71cdbe9 268 else
Sergunb 0:8918a71cdbe9 269 {
Sergunb 0:8918a71cdbe9 270 //Copy the MAC address associated with the specified IPv4 address
Sergunb 0:8918a71cdbe9 271 *macAddr = entry->macAddr;
Sergunb 0:8918a71cdbe9 272
Sergunb 0:8918a71cdbe9 273 //Successful address resolution
Sergunb 0:8918a71cdbe9 274 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 275 }
Sergunb 0:8918a71cdbe9 276 }
Sergunb 0:8918a71cdbe9 277 else
Sergunb 0:8918a71cdbe9 278 {
Sergunb 0:8918a71cdbe9 279 //If no entry exists, then create a new one
Sergunb 0:8918a71cdbe9 280 entry = arpCreateEntry(interface);
Sergunb 0:8918a71cdbe9 281
Sergunb 0:8918a71cdbe9 282 //ARP cache entry successfully created?
Sergunb 0:8918a71cdbe9 283 if(entry != NULL)
Sergunb 0:8918a71cdbe9 284 {
Sergunb 0:8918a71cdbe9 285 //Record the IPv4 address whose MAC address is unknown
Sergunb 0:8918a71cdbe9 286 entry->ipAddr = ipAddr;
Sergunb 0:8918a71cdbe9 287
Sergunb 0:8918a71cdbe9 288 //Reset retransmission counter
Sergunb 0:8918a71cdbe9 289 entry->retransmitCount = 0;
Sergunb 0:8918a71cdbe9 290 //No packet are pending in the transmit queue
Sergunb 0:8918a71cdbe9 291 entry->queueSize = 0;
Sergunb 0:8918a71cdbe9 292
Sergunb 0:8918a71cdbe9 293 //Send an ARP request
Sergunb 0:8918a71cdbe9 294 arpSendRequest(interface, entry->ipAddr, &MAC_BROADCAST_ADDR);
Sergunb 0:8918a71cdbe9 295
Sergunb 0:8918a71cdbe9 296 //Save the time at which the packet was sent
Sergunb 0:8918a71cdbe9 297 entry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 298 //Set timeout value
Sergunb 0:8918a71cdbe9 299 entry->timeout = ARP_REQUEST_TIMEOUT;
Sergunb 0:8918a71cdbe9 300 //Enter INCOMPLETE state
Sergunb 0:8918a71cdbe9 301 entry->state = ARP_STATE_INCOMPLETE;
Sergunb 0:8918a71cdbe9 302
Sergunb 0:8918a71cdbe9 303 //The address resolution is in progress
Sergunb 0:8918a71cdbe9 304 error = ERROR_IN_PROGRESS;
Sergunb 0:8918a71cdbe9 305 }
Sergunb 0:8918a71cdbe9 306 else
Sergunb 0:8918a71cdbe9 307 {
Sergunb 0:8918a71cdbe9 308 //Failed to create ARP cache entry...
Sergunb 0:8918a71cdbe9 309 error = ERROR_OUT_OF_RESOURCES;
Sergunb 0:8918a71cdbe9 310 }
Sergunb 0:8918a71cdbe9 311 }
Sergunb 0:8918a71cdbe9 312
Sergunb 0:8918a71cdbe9 313 //Return status code
Sergunb 0:8918a71cdbe9 314 return error;
Sergunb 0:8918a71cdbe9 315 }
Sergunb 0:8918a71cdbe9 316
Sergunb 0:8918a71cdbe9 317
Sergunb 0:8918a71cdbe9 318 /**
Sergunb 0:8918a71cdbe9 319 * @brief Enqueue an IPv4 packet waiting for address resolution
Sergunb 0:8918a71cdbe9 320 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 321 * @param[in] ipAddr IPv4 address of the destination host
Sergunb 0:8918a71cdbe9 322 * @param[in] buffer Multi-part buffer containing the packet to be enqueued
Sergunb 0:8918a71cdbe9 323 * @param[in] offset Offset to the first byte of the packet
Sergunb 0:8918a71cdbe9 324 * @return Error code
Sergunb 0:8918a71cdbe9 325 **/
Sergunb 0:8918a71cdbe9 326
Sergunb 0:8918a71cdbe9 327 error_t arpEnqueuePacket(NetInterface *interface,
Sergunb 0:8918a71cdbe9 328 Ipv4Addr ipAddr, NetBuffer *buffer, size_t offset)
Sergunb 0:8918a71cdbe9 329 {
Sergunb 0:8918a71cdbe9 330 error_t error;
Sergunb 0:8918a71cdbe9 331 uint_t i;
Sergunb 0:8918a71cdbe9 332 size_t length;
Sergunb 0:8918a71cdbe9 333 ArpCacheEntry *entry;
Sergunb 0:8918a71cdbe9 334
Sergunb 0:8918a71cdbe9 335 //Retrieve the length of the multi-part buffer
Sergunb 0:8918a71cdbe9 336 length = netBufferGetLength(buffer);
Sergunb 0:8918a71cdbe9 337
Sergunb 0:8918a71cdbe9 338 //Search the ARP cache for the specified IPv4 address
Sergunb 0:8918a71cdbe9 339 entry = arpFindEntry(interface, ipAddr);
Sergunb 0:8918a71cdbe9 340
Sergunb 0:8918a71cdbe9 341 //Check whether a matching entry exists
Sergunb 0:8918a71cdbe9 342 if(entry != NULL)
Sergunb 0:8918a71cdbe9 343 {
Sergunb 0:8918a71cdbe9 344 //Check current state
Sergunb 0:8918a71cdbe9 345 if(entry->state == ARP_STATE_INCOMPLETE)
Sergunb 0:8918a71cdbe9 346 {
Sergunb 0:8918a71cdbe9 347 //Check whether the packet queue is full
Sergunb 0:8918a71cdbe9 348 if(entry->queueSize >= ARP_MAX_PENDING_PACKETS)
Sergunb 0:8918a71cdbe9 349 {
Sergunb 0:8918a71cdbe9 350 //When the queue overflows, the new arrival should replace the oldest entry
Sergunb 0:8918a71cdbe9 351 netBufferFree(entry->queue[0].buffer);
Sergunb 0:8918a71cdbe9 352
Sergunb 0:8918a71cdbe9 353 //Make room for the new packet
Sergunb 0:8918a71cdbe9 354 for(i = 1; i < ARP_MAX_PENDING_PACKETS; i++)
Sergunb 0:8918a71cdbe9 355 entry->queue[i - 1] = entry->queue[i];
Sergunb 0:8918a71cdbe9 356
Sergunb 0:8918a71cdbe9 357 //Adjust the number of pending packets
Sergunb 0:8918a71cdbe9 358 entry->queueSize--;
Sergunb 0:8918a71cdbe9 359 }
Sergunb 0:8918a71cdbe9 360
Sergunb 0:8918a71cdbe9 361 //Index of the entry to be filled in
Sergunb 0:8918a71cdbe9 362 i = entry->queueSize;
Sergunb 0:8918a71cdbe9 363 //Allocate a memory buffer to store the packet
Sergunb 0:8918a71cdbe9 364 entry->queue[i].buffer = netBufferAlloc(length);
Sergunb 0:8918a71cdbe9 365
Sergunb 0:8918a71cdbe9 366 //Successful memory allocation?
Sergunb 0:8918a71cdbe9 367 if(entry->queue[i].buffer != NULL)
Sergunb 0:8918a71cdbe9 368 {
Sergunb 0:8918a71cdbe9 369 //Copy the contents of the IPv4 packet
Sergunb 0:8918a71cdbe9 370 netBufferCopy(entry->queue[i].buffer, 0, buffer, 0, length);
Sergunb 0:8918a71cdbe9 371 //Offset to the first byte of the IPv4 header
Sergunb 0:8918a71cdbe9 372 entry->queue[i].offset = offset;
Sergunb 0:8918a71cdbe9 373
Sergunb 0:8918a71cdbe9 374 //Increment the number of queued packets
Sergunb 0:8918a71cdbe9 375 entry->queueSize++;
Sergunb 0:8918a71cdbe9 376 //The packet was successfully enqueued
Sergunb 0:8918a71cdbe9 377 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 378 }
Sergunb 0:8918a71cdbe9 379 else
Sergunb 0:8918a71cdbe9 380 {
Sergunb 0:8918a71cdbe9 381 //Failed to allocate memory
Sergunb 0:8918a71cdbe9 382 error = ERROR_OUT_OF_MEMORY;
Sergunb 0:8918a71cdbe9 383 }
Sergunb 0:8918a71cdbe9 384 }
Sergunb 0:8918a71cdbe9 385 else
Sergunb 0:8918a71cdbe9 386 {
Sergunb 0:8918a71cdbe9 387 //The address is already resolved
Sergunb 0:8918a71cdbe9 388 error = ERROR_UNEXPECTED_STATE;
Sergunb 0:8918a71cdbe9 389 }
Sergunb 0:8918a71cdbe9 390 }
Sergunb 0:8918a71cdbe9 391 else
Sergunb 0:8918a71cdbe9 392 {
Sergunb 0:8918a71cdbe9 393 //No matching entry in ARP cache
Sergunb 0:8918a71cdbe9 394 error = ERROR_NOT_FOUND;
Sergunb 0:8918a71cdbe9 395 }
Sergunb 0:8918a71cdbe9 396
Sergunb 0:8918a71cdbe9 397 //Return status code
Sergunb 0:8918a71cdbe9 398 return error;
Sergunb 0:8918a71cdbe9 399 }
Sergunb 0:8918a71cdbe9 400
Sergunb 0:8918a71cdbe9 401
Sergunb 0:8918a71cdbe9 402 /**
Sergunb 0:8918a71cdbe9 403 * @brief ARP timer handler
Sergunb 0:8918a71cdbe9 404 *
Sergunb 0:8918a71cdbe9 405 * This routine must be periodically called by the TCP/IP stack to
Sergunb 0:8918a71cdbe9 406 * manage ARP cache
Sergunb 0:8918a71cdbe9 407 *
Sergunb 0:8918a71cdbe9 408 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 409 **/
Sergunb 0:8918a71cdbe9 410
Sergunb 0:8918a71cdbe9 411 void arpTick(NetInterface *interface)
Sergunb 0:8918a71cdbe9 412 {
Sergunb 0:8918a71cdbe9 413 uint_t i;
Sergunb 0:8918a71cdbe9 414 systime_t time;
Sergunb 0:8918a71cdbe9 415 ArpCacheEntry *entry;
Sergunb 0:8918a71cdbe9 416
Sergunb 0:8918a71cdbe9 417 //Get current time
Sergunb 0:8918a71cdbe9 418 time = osGetSystemTime();
Sergunb 0:8918a71cdbe9 419
Sergunb 0:8918a71cdbe9 420 //Go through ARP cache
Sergunb 0:8918a71cdbe9 421 for(i = 0; i < ARP_CACHE_SIZE; i++)
Sergunb 0:8918a71cdbe9 422 {
Sergunb 0:8918a71cdbe9 423 //Point to the current entry
Sergunb 0:8918a71cdbe9 424 entry = &interface->arpCache[i];
Sergunb 0:8918a71cdbe9 425
Sergunb 0:8918a71cdbe9 426 //INCOMPLETE state?
Sergunb 0:8918a71cdbe9 427 if(entry->state == ARP_STATE_INCOMPLETE)
Sergunb 0:8918a71cdbe9 428 {
Sergunb 0:8918a71cdbe9 429 //The request timed out?
Sergunb 0:8918a71cdbe9 430 if(timeCompare(time, entry->timestamp + entry->timeout) >= 0)
Sergunb 0:8918a71cdbe9 431 {
Sergunb 0:8918a71cdbe9 432 //Increment retransmission counter
Sergunb 0:8918a71cdbe9 433 entry->retransmitCount++;
Sergunb 0:8918a71cdbe9 434
Sergunb 0:8918a71cdbe9 435 //Check whether the maximum number of retransmissions has been exceeded
Sergunb 0:8918a71cdbe9 436 if(entry->retransmitCount < ARP_MAX_REQUESTS)
Sergunb 0:8918a71cdbe9 437 {
Sergunb 0:8918a71cdbe9 438 //Retransmit ARP request
Sergunb 0:8918a71cdbe9 439 arpSendRequest(interface, entry->ipAddr, &MAC_BROADCAST_ADDR);
Sergunb 0:8918a71cdbe9 440
Sergunb 0:8918a71cdbe9 441 //Save the time at which the packet was sent
Sergunb 0:8918a71cdbe9 442 entry->timestamp = time;
Sergunb 0:8918a71cdbe9 443 //Set timeout value
Sergunb 0:8918a71cdbe9 444 entry->timeout = ARP_REQUEST_TIMEOUT;
Sergunb 0:8918a71cdbe9 445 }
Sergunb 0:8918a71cdbe9 446 else
Sergunb 0:8918a71cdbe9 447 {
Sergunb 0:8918a71cdbe9 448 //Drop packets that are waiting for address resolution
Sergunb 0:8918a71cdbe9 449 arpFlushQueuedPackets(interface, entry);
Sergunb 0:8918a71cdbe9 450 //The entry should be deleted since address resolution has failed
Sergunb 0:8918a71cdbe9 451 entry->state = ARP_STATE_NONE;
Sergunb 0:8918a71cdbe9 452 }
Sergunb 0:8918a71cdbe9 453 }
Sergunb 0:8918a71cdbe9 454 }
Sergunb 0:8918a71cdbe9 455 //REACHABLE state?
Sergunb 0:8918a71cdbe9 456 else if(entry->state == ARP_STATE_REACHABLE)
Sergunb 0:8918a71cdbe9 457 {
Sergunb 0:8918a71cdbe9 458 //Periodically time out ARP cache entries
Sergunb 0:8918a71cdbe9 459 if(timeCompare(time, entry->timestamp + entry->timeout) >= 0)
Sergunb 0:8918a71cdbe9 460 {
Sergunb 0:8918a71cdbe9 461 //Save current time
Sergunb 0:8918a71cdbe9 462 entry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 463 //Enter STALE state
Sergunb 0:8918a71cdbe9 464 entry->state = ARP_STATE_STALE;
Sergunb 0:8918a71cdbe9 465 }
Sergunb 0:8918a71cdbe9 466 }
Sergunb 0:8918a71cdbe9 467 //DELAY state?
Sergunb 0:8918a71cdbe9 468 else if(entry->state == ARP_STATE_DELAY)
Sergunb 0:8918a71cdbe9 469 {
Sergunb 0:8918a71cdbe9 470 //Wait for the specified delay before sending the first probe
Sergunb 0:8918a71cdbe9 471 if(timeCompare(time, entry->timestamp + entry->timeout) >= 0)
Sergunb 0:8918a71cdbe9 472 {
Sergunb 0:8918a71cdbe9 473 //Send a point-to-point ARP request to the host
Sergunb 0:8918a71cdbe9 474 arpSendRequest(interface, entry->ipAddr, &entry->macAddr);
Sergunb 0:8918a71cdbe9 475
Sergunb 0:8918a71cdbe9 476 //Save the time at which the packet was sent
Sergunb 0:8918a71cdbe9 477 entry->timestamp = time;
Sergunb 0:8918a71cdbe9 478 //Set timeout value
Sergunb 0:8918a71cdbe9 479 entry->timeout = ARP_PROBE_TIMEOUT;
Sergunb 0:8918a71cdbe9 480 //Switch to the PROBE state
Sergunb 0:8918a71cdbe9 481 entry->state = ARP_STATE_PROBE;
Sergunb 0:8918a71cdbe9 482 }
Sergunb 0:8918a71cdbe9 483 }
Sergunb 0:8918a71cdbe9 484 //PROBE state?
Sergunb 0:8918a71cdbe9 485 else if(entry->state == ARP_STATE_PROBE)
Sergunb 0:8918a71cdbe9 486 {
Sergunb 0:8918a71cdbe9 487 //The request timed out?
Sergunb 0:8918a71cdbe9 488 if(timeCompare(time, entry->timestamp + entry->timeout) >= 0)
Sergunb 0:8918a71cdbe9 489 {
Sergunb 0:8918a71cdbe9 490 //Increment retransmission counter
Sergunb 0:8918a71cdbe9 491 entry->retransmitCount++;
Sergunb 0:8918a71cdbe9 492
Sergunb 0:8918a71cdbe9 493 //Check whether the maximum number of retransmissions has been exceeded
Sergunb 0:8918a71cdbe9 494 if(entry->retransmitCount < ARP_MAX_PROBES)
Sergunb 0:8918a71cdbe9 495 {
Sergunb 0:8918a71cdbe9 496 //Send a point-to-point ARP request to the host
Sergunb 0:8918a71cdbe9 497 arpSendRequest(interface, entry->ipAddr, &entry->macAddr);
Sergunb 0:8918a71cdbe9 498
Sergunb 0:8918a71cdbe9 499 //Save the time at which the packet was sent
Sergunb 0:8918a71cdbe9 500 entry->timestamp = time;
Sergunb 0:8918a71cdbe9 501 //Set timeout value
Sergunb 0:8918a71cdbe9 502 entry->timeout = ARP_PROBE_TIMEOUT;
Sergunb 0:8918a71cdbe9 503 }
Sergunb 0:8918a71cdbe9 504 else
Sergunb 0:8918a71cdbe9 505 {
Sergunb 0:8918a71cdbe9 506 //The entry should be deleted since the host is not reachable anymore
Sergunb 0:8918a71cdbe9 507 entry->state = ARP_STATE_NONE;
Sergunb 0:8918a71cdbe9 508 }
Sergunb 0:8918a71cdbe9 509 }
Sergunb 0:8918a71cdbe9 510 }
Sergunb 0:8918a71cdbe9 511 }
Sergunb 0:8918a71cdbe9 512 }
Sergunb 0:8918a71cdbe9 513
Sergunb 0:8918a71cdbe9 514
Sergunb 0:8918a71cdbe9 515 /**
Sergunb 0:8918a71cdbe9 516 * @brief Incoming ARP packet processing
Sergunb 0:8918a71cdbe9 517 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 518 * @param[in] arpPacket Incoming ARP packet
Sergunb 0:8918a71cdbe9 519 * @param[in] length Packet length
Sergunb 0:8918a71cdbe9 520 **/
Sergunb 0:8918a71cdbe9 521
Sergunb 0:8918a71cdbe9 522 void arpProcessPacket(NetInterface *interface, ArpPacket *arpPacket, size_t length)
Sergunb 0:8918a71cdbe9 523 {
Sergunb 0:8918a71cdbe9 524 //Discard invalid ARP packets
Sergunb 0:8918a71cdbe9 525 if(length < sizeof(ArpPacket))
Sergunb 0:8918a71cdbe9 526 return;
Sergunb 0:8918a71cdbe9 527
Sergunb 0:8918a71cdbe9 528 //Debug message
Sergunb 0:8918a71cdbe9 529 TRACE_INFO("ARP packet received (%" PRIuSIZE " bytes)...\r\n", length);
Sergunb 0:8918a71cdbe9 530 //Dump ARP packet contents for debugging purpose
Sergunb 0:8918a71cdbe9 531 arpDumpPacket(arpPacket);
Sergunb 0:8918a71cdbe9 532
Sergunb 0:8918a71cdbe9 533 //Make sure the hardware type is valid
Sergunb 0:8918a71cdbe9 534 if(arpPacket->hrd != HTONS(ARP_HARDWARE_TYPE_ETH))
Sergunb 0:8918a71cdbe9 535 return;
Sergunb 0:8918a71cdbe9 536 //Make sure the protocol type is valid
Sergunb 0:8918a71cdbe9 537 if(arpPacket->pro != HTONS(ARP_PROTOCOL_TYPE_IPV4))
Sergunb 0:8918a71cdbe9 538 return;
Sergunb 0:8918a71cdbe9 539 //Check the length of the hardware address
Sergunb 0:8918a71cdbe9 540 if(arpPacket->hln != sizeof(MacAddr))
Sergunb 0:8918a71cdbe9 541 return;
Sergunb 0:8918a71cdbe9 542 //Check the length of the protocol address
Sergunb 0:8918a71cdbe9 543 if(arpPacket->pln != sizeof(Ipv4Addr))
Sergunb 0:8918a71cdbe9 544 return;
Sergunb 0:8918a71cdbe9 545
Sergunb 0:8918a71cdbe9 546 //Check the state of the host address
Sergunb 0:8918a71cdbe9 547 if(interface->ipv4Context.addrState == IPV4_ADDR_STATE_TENTATIVE)
Sergunb 0:8918a71cdbe9 548 {
Sergunb 0:8918a71cdbe9 549 //If the host receives any ARP packet where the sender IP address is
Sergunb 0:8918a71cdbe9 550 //the address being probed for, then this is a conflicting ARP packet
Sergunb 0:8918a71cdbe9 551 if(arpPacket->spa == interface->ipv4Context.addr)
Sergunb 0:8918a71cdbe9 552 {
Sergunb 0:8918a71cdbe9 553 //An address conflict has been detected...
Sergunb 0:8918a71cdbe9 554 interface->ipv4Context.addrConflict = TRUE;
Sergunb 0:8918a71cdbe9 555 //Exit immediately
Sergunb 0:8918a71cdbe9 556 return;
Sergunb 0:8918a71cdbe9 557 }
Sergunb 0:8918a71cdbe9 558 }
Sergunb 0:8918a71cdbe9 559 else if(interface->ipv4Context.addrState == IPV4_ADDR_STATE_VALID)
Sergunb 0:8918a71cdbe9 560 {
Sergunb 0:8918a71cdbe9 561 //Check whether the sender protocol address matches the IP
Sergunb 0:8918a71cdbe9 562 //address assigned to the interface
Sergunb 0:8918a71cdbe9 563 if(arpPacket->spa == interface->ipv4Context.addr)
Sergunb 0:8918a71cdbe9 564 {
Sergunb 0:8918a71cdbe9 565 //If the sender hardware address does not match the hardware
Sergunb 0:8918a71cdbe9 566 //address of that interface, then this is a conflicting ARP packet
Sergunb 0:8918a71cdbe9 567 if(!macCompAddr(&arpPacket->sha, &interface->macAddr))
Sergunb 0:8918a71cdbe9 568 {
Sergunb 0:8918a71cdbe9 569 //An address conflict has been detected...
Sergunb 0:8918a71cdbe9 570 interface->ipv4Context.addrConflict = TRUE;
Sergunb 0:8918a71cdbe9 571 //Exit immediately
Sergunb 0:8918a71cdbe9 572 return;
Sergunb 0:8918a71cdbe9 573 }
Sergunb 0:8918a71cdbe9 574 }
Sergunb 0:8918a71cdbe9 575 }
Sergunb 0:8918a71cdbe9 576
Sergunb 0:8918a71cdbe9 577 //Check whether the target protocol address matches the IP
Sergunb 0:8918a71cdbe9 578 //address assigned to the interface
Sergunb 0:8918a71cdbe9 579 if(arpPacket->tpa != interface->ipv4Context.addr)
Sergunb 0:8918a71cdbe9 580 return;
Sergunb 0:8918a71cdbe9 581
Sergunb 0:8918a71cdbe9 582 //Check operation code
Sergunb 0:8918a71cdbe9 583 switch(ntohs(arpPacket->op))
Sergunb 0:8918a71cdbe9 584 {
Sergunb 0:8918a71cdbe9 585 //ARP request?
Sergunb 0:8918a71cdbe9 586 case ARP_OPCODE_ARP_REQUEST:
Sergunb 0:8918a71cdbe9 587 //Process incoming ARP request
Sergunb 0:8918a71cdbe9 588 arpProcessRequest(interface, arpPacket);
Sergunb 0:8918a71cdbe9 589 break;
Sergunb 0:8918a71cdbe9 590 //ARP reply?
Sergunb 0:8918a71cdbe9 591 case ARP_OPCODE_ARP_REPLY:
Sergunb 0:8918a71cdbe9 592 //Process incoming ARP reply
Sergunb 0:8918a71cdbe9 593 arpProcessReply(interface, arpPacket);
Sergunb 0:8918a71cdbe9 594 break;
Sergunb 0:8918a71cdbe9 595 //Unknown operation code?
Sergunb 0:8918a71cdbe9 596 default:
Sergunb 0:8918a71cdbe9 597 //Debug message
Sergunb 0:8918a71cdbe9 598 TRACE_INFO("Unknown operation code!\r\n");
Sergunb 0:8918a71cdbe9 599 //Discard incoming packet
Sergunb 0:8918a71cdbe9 600 break;
Sergunb 0:8918a71cdbe9 601 }
Sergunb 0:8918a71cdbe9 602 }
Sergunb 0:8918a71cdbe9 603
Sergunb 0:8918a71cdbe9 604
Sergunb 0:8918a71cdbe9 605 /**
Sergunb 0:8918a71cdbe9 606 * @brief Incoming ARP request processing
Sergunb 0:8918a71cdbe9 607 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 608 * @param[in] arpRequest Incoming ARP request
Sergunb 0:8918a71cdbe9 609 **/
Sergunb 0:8918a71cdbe9 610
Sergunb 0:8918a71cdbe9 611 void arpProcessRequest(NetInterface *interface, ArpPacket *arpRequest)
Sergunb 0:8918a71cdbe9 612 {
Sergunb 0:8918a71cdbe9 613 //Debug message
Sergunb 0:8918a71cdbe9 614 TRACE_INFO("ARP Request received...\r\n");
Sergunb 0:8918a71cdbe9 615
Sergunb 0:8918a71cdbe9 616 //Check sender protocol address
Sergunb 0:8918a71cdbe9 617 if(ipv4IsBroadcastAddr(interface, arpRequest->spa))
Sergunb 0:8918a71cdbe9 618 return;
Sergunb 0:8918a71cdbe9 619 if(ipv4IsMulticastAddr(arpRequest->spa))
Sergunb 0:8918a71cdbe9 620 return;
Sergunb 0:8918a71cdbe9 621
Sergunb 0:8918a71cdbe9 622 //Check whether the target IP address is an address being probed for
Sergunb 0:8918a71cdbe9 623 if(ipv4IsTentativeAddr(interface, arpRequest->tpa))
Sergunb 0:8918a71cdbe9 624 {
Sergunb 0:8918a71cdbe9 625 //ARP probe received?
Sergunb 0:8918a71cdbe9 626 if(arpRequest->spa == IPV4_UNSPECIFIED_ADDR)
Sergunb 0:8918a71cdbe9 627 {
Sergunb 0:8918a71cdbe9 628 //If the sender hardware address does not match the hardware
Sergunb 0:8918a71cdbe9 629 //address of that interface, then this is a conflicting ARP packet
Sergunb 0:8918a71cdbe9 630 if(!macCompAddr(&arpRequest->sha, &interface->macAddr))
Sergunb 0:8918a71cdbe9 631 {
Sergunb 0:8918a71cdbe9 632 //An address conflict has been detected...
Sergunb 0:8918a71cdbe9 633 interface->ipv4Context.addrConflict = TRUE;
Sergunb 0:8918a71cdbe9 634 }
Sergunb 0:8918a71cdbe9 635 }
Sergunb 0:8918a71cdbe9 636
Sergunb 0:8918a71cdbe9 637 //In all cases, the host must not respond to an ARP request for an
Sergunb 0:8918a71cdbe9 638 //address being probed for
Sergunb 0:8918a71cdbe9 639 return;
Sergunb 0:8918a71cdbe9 640 }
Sergunb 0:8918a71cdbe9 641
Sergunb 0:8918a71cdbe9 642 //Send ARP reply
Sergunb 0:8918a71cdbe9 643 arpSendReply(interface, arpRequest->spa, &arpRequest->sha, &arpRequest->sha);
Sergunb 0:8918a71cdbe9 644 }
Sergunb 0:8918a71cdbe9 645
Sergunb 0:8918a71cdbe9 646
Sergunb 0:8918a71cdbe9 647 /**
Sergunb 0:8918a71cdbe9 648 * @brief Incoming ARP reply processing
Sergunb 0:8918a71cdbe9 649 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 650 * @param[in] arpReply Incoming ARP reply
Sergunb 0:8918a71cdbe9 651 **/
Sergunb 0:8918a71cdbe9 652
Sergunb 0:8918a71cdbe9 653 void arpProcessReply(NetInterface *interface, ArpPacket *arpReply)
Sergunb 0:8918a71cdbe9 654 {
Sergunb 0:8918a71cdbe9 655 ArpCacheEntry *entry;
Sergunb 0:8918a71cdbe9 656
Sergunb 0:8918a71cdbe9 657 //Debug message
Sergunb 0:8918a71cdbe9 658 TRACE_INFO("ARP Reply received...\r\n");
Sergunb 0:8918a71cdbe9 659
Sergunb 0:8918a71cdbe9 660 //Check sender protocol address
Sergunb 0:8918a71cdbe9 661 if(arpReply->spa == IPV4_UNSPECIFIED_ADDR)
Sergunb 0:8918a71cdbe9 662 return;
Sergunb 0:8918a71cdbe9 663 if(ipv4IsBroadcastAddr(interface, arpReply->spa))
Sergunb 0:8918a71cdbe9 664 return;
Sergunb 0:8918a71cdbe9 665 if(ipv4IsMulticastAddr(arpReply->spa))
Sergunb 0:8918a71cdbe9 666 return;
Sergunb 0:8918a71cdbe9 667
Sergunb 0:8918a71cdbe9 668 //Check sender hardware address
Sergunb 0:8918a71cdbe9 669 if(macCompAddr(&arpReply->sha, &MAC_UNSPECIFIED_ADDR))
Sergunb 0:8918a71cdbe9 670 return;
Sergunb 0:8918a71cdbe9 671 if(macCompAddr(&arpReply->sha, &MAC_BROADCAST_ADDR))
Sergunb 0:8918a71cdbe9 672 return;
Sergunb 0:8918a71cdbe9 673 if(macIsMulticastAddr(&arpReply->sha))
Sergunb 0:8918a71cdbe9 674 return;
Sergunb 0:8918a71cdbe9 675
Sergunb 0:8918a71cdbe9 676 //Check whether the target IP address is an address being probed for
Sergunb 0:8918a71cdbe9 677 if(ipv4IsTentativeAddr(interface, arpReply->tpa))
Sergunb 0:8918a71cdbe9 678 return;
Sergunb 0:8918a71cdbe9 679
Sergunb 0:8918a71cdbe9 680 //Search the ARP cache for the specified IPv4 address
Sergunb 0:8918a71cdbe9 681 entry = arpFindEntry(interface, arpReply->spa);
Sergunb 0:8918a71cdbe9 682
Sergunb 0:8918a71cdbe9 683 //Check whether a matching entry has been found
Sergunb 0:8918a71cdbe9 684 if(entry != NULL)
Sergunb 0:8918a71cdbe9 685 {
Sergunb 0:8918a71cdbe9 686 //Check current state
Sergunb 0:8918a71cdbe9 687 if(entry->state == ARP_STATE_INCOMPLETE)
Sergunb 0:8918a71cdbe9 688 {
Sergunb 0:8918a71cdbe9 689 //Record the corresponding MAC address
Sergunb 0:8918a71cdbe9 690 entry->macAddr = arpReply->sha;
Sergunb 0:8918a71cdbe9 691
Sergunb 0:8918a71cdbe9 692 //Send all the packets that are pending for transmission
Sergunb 0:8918a71cdbe9 693 arpSendQueuedPackets(interface, entry);
Sergunb 0:8918a71cdbe9 694
Sergunb 0:8918a71cdbe9 695 //Save current time
Sergunb 0:8918a71cdbe9 696 entry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 697 //The validity of the ARP entry is limited in time
Sergunb 0:8918a71cdbe9 698 entry->timeout = ARP_REACHABLE_TIME;
Sergunb 0:8918a71cdbe9 699 //Switch to the REACHABLE state
Sergunb 0:8918a71cdbe9 700 entry->state = ARP_STATE_REACHABLE;
Sergunb 0:8918a71cdbe9 701 }
Sergunb 0:8918a71cdbe9 702 else if(entry->state == ARP_STATE_REACHABLE)
Sergunb 0:8918a71cdbe9 703 {
Sergunb 0:8918a71cdbe9 704 //Different link-layer address than cached?
Sergunb 0:8918a71cdbe9 705 if(!macCompAddr(&arpReply->sha, &entry->macAddr))
Sergunb 0:8918a71cdbe9 706 {
Sergunb 0:8918a71cdbe9 707 //Enter STALE state
Sergunb 0:8918a71cdbe9 708 entry->state = ARP_STATE_STALE;
Sergunb 0:8918a71cdbe9 709 }
Sergunb 0:8918a71cdbe9 710 }
Sergunb 0:8918a71cdbe9 711 else if(entry->state == ARP_STATE_PROBE)
Sergunb 0:8918a71cdbe9 712 {
Sergunb 0:8918a71cdbe9 713 //Record IPv4/MAC address pair
Sergunb 0:8918a71cdbe9 714 entry->ipAddr = arpReply->spa;
Sergunb 0:8918a71cdbe9 715 entry->macAddr = arpReply->sha;
Sergunb 0:8918a71cdbe9 716
Sergunb 0:8918a71cdbe9 717 //Save current time
Sergunb 0:8918a71cdbe9 718 entry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 719 //The validity of the ARP entry is limited in time
Sergunb 0:8918a71cdbe9 720 entry->timeout = ARP_REACHABLE_TIME;
Sergunb 0:8918a71cdbe9 721 //Switch to the REACHABLE state
Sergunb 0:8918a71cdbe9 722 entry->state = ARP_STATE_REACHABLE;
Sergunb 0:8918a71cdbe9 723 }
Sergunb 0:8918a71cdbe9 724 }
Sergunb 0:8918a71cdbe9 725 }
Sergunb 0:8918a71cdbe9 726
Sergunb 0:8918a71cdbe9 727
Sergunb 0:8918a71cdbe9 728 /**
Sergunb 0:8918a71cdbe9 729 * @brief Send ARP probe
Sergunb 0:8918a71cdbe9 730 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 731 * @param[in] targetIpAddr Target IPv4 address
Sergunb 0:8918a71cdbe9 732 * @return Error code
Sergunb 0:8918a71cdbe9 733 **/
Sergunb 0:8918a71cdbe9 734
Sergunb 0:8918a71cdbe9 735 error_t arpSendProbe(NetInterface *interface, Ipv4Addr targetIpAddr)
Sergunb 0:8918a71cdbe9 736 {
Sergunb 0:8918a71cdbe9 737 error_t error;
Sergunb 0:8918a71cdbe9 738 size_t offset;
Sergunb 0:8918a71cdbe9 739 NetBuffer *buffer;
Sergunb 0:8918a71cdbe9 740 ArpPacket *arpRequest;
Sergunb 0:8918a71cdbe9 741
Sergunb 0:8918a71cdbe9 742 //Allocate a memory buffer to hold an ARP packet
Sergunb 0:8918a71cdbe9 743 buffer = ethAllocBuffer(sizeof(ArpPacket), &offset);
Sergunb 0:8918a71cdbe9 744 //Failed to allocate buffer?
Sergunb 0:8918a71cdbe9 745 if(buffer == NULL)
Sergunb 0:8918a71cdbe9 746 return ERROR_OUT_OF_MEMORY;
Sergunb 0:8918a71cdbe9 747
Sergunb 0:8918a71cdbe9 748 //Point to the beginning of the ARP packet
Sergunb 0:8918a71cdbe9 749 arpRequest = netBufferAt(buffer, offset);
Sergunb 0:8918a71cdbe9 750
Sergunb 0:8918a71cdbe9 751 //Format ARP request
Sergunb 0:8918a71cdbe9 752 arpRequest->hrd = htons(ARP_HARDWARE_TYPE_ETH);
Sergunb 0:8918a71cdbe9 753 arpRequest->pro = htons(ARP_PROTOCOL_TYPE_IPV4);
Sergunb 0:8918a71cdbe9 754 arpRequest->hln = sizeof(MacAddr);
Sergunb 0:8918a71cdbe9 755 arpRequest->pln = sizeof(Ipv4Addr);
Sergunb 0:8918a71cdbe9 756 arpRequest->op = htons(ARP_OPCODE_ARP_REQUEST);
Sergunb 0:8918a71cdbe9 757 arpRequest->sha = interface->macAddr;
Sergunb 0:8918a71cdbe9 758 arpRequest->spa = IPV4_UNSPECIFIED_ADDR;
Sergunb 0:8918a71cdbe9 759 arpRequest->tha = MAC_UNSPECIFIED_ADDR;
Sergunb 0:8918a71cdbe9 760 arpRequest->tpa = targetIpAddr;
Sergunb 0:8918a71cdbe9 761
Sergunb 0:8918a71cdbe9 762 //Debug message
Sergunb 0:8918a71cdbe9 763 TRACE_INFO("Sending ARP Probe (%" PRIuSIZE " bytes)...\r\n", sizeof(ArpPacket));
Sergunb 0:8918a71cdbe9 764 //Dump ARP packet contents for debugging purpose
Sergunb 0:8918a71cdbe9 765 arpDumpPacket(arpRequest);
Sergunb 0:8918a71cdbe9 766
Sergunb 0:8918a71cdbe9 767 //Send ARP request
Sergunb 0:8918a71cdbe9 768 error = ethSendFrame(interface, &MAC_BROADCAST_ADDR,
Sergunb 0:8918a71cdbe9 769 buffer, offset, ETH_TYPE_ARP);
Sergunb 0:8918a71cdbe9 770
Sergunb 0:8918a71cdbe9 771 //Free previously allocated memory
Sergunb 0:8918a71cdbe9 772 netBufferFree(buffer);
Sergunb 0:8918a71cdbe9 773 //Return status code
Sergunb 0:8918a71cdbe9 774 return error;
Sergunb 0:8918a71cdbe9 775 }
Sergunb 0:8918a71cdbe9 776
Sergunb 0:8918a71cdbe9 777
Sergunb 0:8918a71cdbe9 778 /**
Sergunb 0:8918a71cdbe9 779 * @brief Send ARP request
Sergunb 0:8918a71cdbe9 780 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 781 * @param[in] targetIpAddr Target IPv4 address
Sergunb 0:8918a71cdbe9 782 * @param[in] destMacAddr Destination MAC address
Sergunb 0:8918a71cdbe9 783 * @return Error code
Sergunb 0:8918a71cdbe9 784 **/
Sergunb 0:8918a71cdbe9 785
Sergunb 0:8918a71cdbe9 786 error_t arpSendRequest(NetInterface *interface,
Sergunb 0:8918a71cdbe9 787 Ipv4Addr targetIpAddr, const MacAddr *destMacAddr)
Sergunb 0:8918a71cdbe9 788 {
Sergunb 0:8918a71cdbe9 789 error_t error;
Sergunb 0:8918a71cdbe9 790 size_t offset;
Sergunb 0:8918a71cdbe9 791 NetBuffer *buffer;
Sergunb 0:8918a71cdbe9 792 ArpPacket *arpRequest;
Sergunb 0:8918a71cdbe9 793 Ipv4Addr senderIpAddr;
Sergunb 0:8918a71cdbe9 794
Sergunb 0:8918a71cdbe9 795 //Select the most appropriate sender IP address to be used
Sergunb 0:8918a71cdbe9 796 error = ipv4SelectSourceAddr(&interface, targetIpAddr, &senderIpAddr);
Sergunb 0:8918a71cdbe9 797 //No address assigned to the interface?
Sergunb 0:8918a71cdbe9 798 if(error)
Sergunb 0:8918a71cdbe9 799 return error;
Sergunb 0:8918a71cdbe9 800
Sergunb 0:8918a71cdbe9 801 //Allocate a memory buffer to hold an ARP packet
Sergunb 0:8918a71cdbe9 802 buffer = ethAllocBuffer(sizeof(ArpPacket), &offset);
Sergunb 0:8918a71cdbe9 803 //Failed to allocate buffer?
Sergunb 0:8918a71cdbe9 804 if(buffer == NULL)
Sergunb 0:8918a71cdbe9 805 return ERROR_OUT_OF_MEMORY;
Sergunb 0:8918a71cdbe9 806
Sergunb 0:8918a71cdbe9 807 //Point to the beginning of the ARP packet
Sergunb 0:8918a71cdbe9 808 arpRequest = netBufferAt(buffer, offset);
Sergunb 0:8918a71cdbe9 809
Sergunb 0:8918a71cdbe9 810 //Format ARP request
Sergunb 0:8918a71cdbe9 811 arpRequest->hrd = htons(ARP_HARDWARE_TYPE_ETH);
Sergunb 0:8918a71cdbe9 812 arpRequest->pro = htons(ARP_PROTOCOL_TYPE_IPV4);
Sergunb 0:8918a71cdbe9 813 arpRequest->hln = sizeof(MacAddr);
Sergunb 0:8918a71cdbe9 814 arpRequest->pln = sizeof(Ipv4Addr);
Sergunb 0:8918a71cdbe9 815 arpRequest->op = htons(ARP_OPCODE_ARP_REQUEST);
Sergunb 0:8918a71cdbe9 816 arpRequest->sha = interface->macAddr;
Sergunb 0:8918a71cdbe9 817 arpRequest->spa = senderIpAddr;
Sergunb 0:8918a71cdbe9 818 arpRequest->tha = MAC_UNSPECIFIED_ADDR;
Sergunb 0:8918a71cdbe9 819 arpRequest->tpa = targetIpAddr;
Sergunb 0:8918a71cdbe9 820
Sergunb 0:8918a71cdbe9 821 //Debug message
Sergunb 0:8918a71cdbe9 822 TRACE_INFO("Sending ARP Request (%" PRIuSIZE " bytes)...\r\n", sizeof(ArpPacket));
Sergunb 0:8918a71cdbe9 823 //Dump ARP packet contents for debugging purpose
Sergunb 0:8918a71cdbe9 824 arpDumpPacket(arpRequest);
Sergunb 0:8918a71cdbe9 825
Sergunb 0:8918a71cdbe9 826 //Send ARP request
Sergunb 0:8918a71cdbe9 827 error = ethSendFrame(interface, destMacAddr, buffer, offset, ETH_TYPE_ARP);
Sergunb 0:8918a71cdbe9 828
Sergunb 0:8918a71cdbe9 829 //Free previously allocated memory
Sergunb 0:8918a71cdbe9 830 netBufferFree(buffer);
Sergunb 0:8918a71cdbe9 831 //Return status code
Sergunb 0:8918a71cdbe9 832 return error;
Sergunb 0:8918a71cdbe9 833 }
Sergunb 0:8918a71cdbe9 834
Sergunb 0:8918a71cdbe9 835
Sergunb 0:8918a71cdbe9 836 /**
Sergunb 0:8918a71cdbe9 837 * @brief Send ARP reply
Sergunb 0:8918a71cdbe9 838 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 839 * @param[in] targetIpAddr Target IPv4 address
Sergunb 0:8918a71cdbe9 840 * @param[in] targetMacAddr Target MAC address
Sergunb 0:8918a71cdbe9 841 * @param[in] destMacAddr Destination MAC address
Sergunb 0:8918a71cdbe9 842 * @return Error code
Sergunb 0:8918a71cdbe9 843 **/
Sergunb 0:8918a71cdbe9 844
Sergunb 0:8918a71cdbe9 845 error_t arpSendReply(NetInterface *interface, Ipv4Addr targetIpAddr,
Sergunb 0:8918a71cdbe9 846 const MacAddr *targetMacAddr, const MacAddr *destMacAddr)
Sergunb 0:8918a71cdbe9 847 {
Sergunb 0:8918a71cdbe9 848 error_t error;
Sergunb 0:8918a71cdbe9 849 size_t offset;
Sergunb 0:8918a71cdbe9 850 NetBuffer *buffer;
Sergunb 0:8918a71cdbe9 851 ArpPacket *arpReply;
Sergunb 0:8918a71cdbe9 852
Sergunb 0:8918a71cdbe9 853 //Allocate a memory buffer to hold an ARP packet
Sergunb 0:8918a71cdbe9 854 buffer = ethAllocBuffer(sizeof(ArpPacket), &offset);
Sergunb 0:8918a71cdbe9 855 //Failed to allocate buffer?
Sergunb 0:8918a71cdbe9 856 if(buffer == NULL)
Sergunb 0:8918a71cdbe9 857 return ERROR_OUT_OF_MEMORY;
Sergunb 0:8918a71cdbe9 858
Sergunb 0:8918a71cdbe9 859 //Point to the beginning of the ARP packet
Sergunb 0:8918a71cdbe9 860 arpReply = netBufferAt(buffer, offset);
Sergunb 0:8918a71cdbe9 861
Sergunb 0:8918a71cdbe9 862 //Format ARP reply
Sergunb 0:8918a71cdbe9 863 arpReply->hrd = htons(ARP_HARDWARE_TYPE_ETH);
Sergunb 0:8918a71cdbe9 864 arpReply->pro = htons(ETH_TYPE_IPV4);
Sergunb 0:8918a71cdbe9 865 arpReply->hln = sizeof(MacAddr);
Sergunb 0:8918a71cdbe9 866 arpReply->pln = sizeof(Ipv4Addr);
Sergunb 0:8918a71cdbe9 867 arpReply->op = htons(ARP_OPCODE_ARP_REPLY);
Sergunb 0:8918a71cdbe9 868 arpReply->sha = interface->macAddr;
Sergunb 0:8918a71cdbe9 869 arpReply->spa = interface->ipv4Context.addr;
Sergunb 0:8918a71cdbe9 870 arpReply->tha = *targetMacAddr;
Sergunb 0:8918a71cdbe9 871 arpReply->tpa = targetIpAddr;
Sergunb 0:8918a71cdbe9 872
Sergunb 0:8918a71cdbe9 873 //Debug message
Sergunb 0:8918a71cdbe9 874 TRACE_INFO("Sending ARP Reply (%" PRIuSIZE " bytes)...\r\n", sizeof(ArpPacket));
Sergunb 0:8918a71cdbe9 875 //Dump ARP packet contents for debugging purpose
Sergunb 0:8918a71cdbe9 876 arpDumpPacket(arpReply);
Sergunb 0:8918a71cdbe9 877
Sergunb 0:8918a71cdbe9 878 //Send ARP reply
Sergunb 0:8918a71cdbe9 879 error = ethSendFrame(interface, destMacAddr, buffer, offset, ETH_TYPE_ARP);
Sergunb 0:8918a71cdbe9 880
Sergunb 0:8918a71cdbe9 881 //Free previously allocated memory
Sergunb 0:8918a71cdbe9 882 netBufferFree(buffer);
Sergunb 0:8918a71cdbe9 883 //Return status code
Sergunb 0:8918a71cdbe9 884 return error;
Sergunb 0:8918a71cdbe9 885 }
Sergunb 0:8918a71cdbe9 886
Sergunb 0:8918a71cdbe9 887
Sergunb 0:8918a71cdbe9 888 /**
Sergunb 0:8918a71cdbe9 889 * @brief Dump ARP packet for debugging purpose
Sergunb 0:8918a71cdbe9 890 * @param[in] arpPacket ARP header
Sergunb 0:8918a71cdbe9 891 **/
Sergunb 0:8918a71cdbe9 892
Sergunb 0:8918a71cdbe9 893 void arpDumpPacket(const ArpPacket *arpPacket)
Sergunb 0:8918a71cdbe9 894 {
Sergunb 0:8918a71cdbe9 895 //Dump ARP packet contents
Sergunb 0:8918a71cdbe9 896 TRACE_DEBUG(" Hardware Type (hrd) = 0x%04" PRIX16 "\r\n", ntohs(arpPacket->hrd));
Sergunb 0:8918a71cdbe9 897 TRACE_DEBUG(" Protocol Type (pro) = 0x%04" PRIX16 "\r\n", ntohs(arpPacket->pro));
Sergunb 0:8918a71cdbe9 898 TRACE_DEBUG(" Hardware Address Length (hln) = %" PRIu8 "\r\n", arpPacket->hln);
Sergunb 0:8918a71cdbe9 899 TRACE_DEBUG(" Protocol Address Length (pln) = %" PRIu8 "\r\n", arpPacket->pln);
Sergunb 0:8918a71cdbe9 900 TRACE_DEBUG(" Opcode (op) = %" PRIu16 "\r\n", ntohs(arpPacket->op));
Sergunb 0:8918a71cdbe9 901 TRACE_DEBUG(" Sender Hardware Address (sha)= %s\r\n", macAddrToString(&arpPacket->sha, NULL));
Sergunb 0:8918a71cdbe9 902 TRACE_DEBUG(" Sender Protocol Address (spa) = %s\r\n", ipv4AddrToString(arpPacket->spa, NULL));
Sergunb 0:8918a71cdbe9 903 TRACE_DEBUG(" Target Hardware Address (tha)= %s\r\n", macAddrToString(&arpPacket->tha, NULL));
Sergunb 0:8918a71cdbe9 904 TRACE_DEBUG(" Target Protocol Address (tpa) = %s\r\n", ipv4AddrToString(arpPacket->tpa, NULL));
Sergunb 0:8918a71cdbe9 905 }
Sergunb 0:8918a71cdbe9 906
Sergunb 0:8918a71cdbe9 907 #endif
Sergunb 0:8918a71cdbe9 908