Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
arp.c
00001 /** 00002 * @file arp.c 00003 * @brief ARP (Address Resolution Protocol) 00004 * 00005 * @section License 00006 * 00007 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. 00008 * 00009 * This file is part of CycloneTCP Open. 00010 * 00011 * This program is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU General Public License 00013 * as published by the Free Software Foundation; either version 2 00014 * of the License, or (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License 00022 * along with this program; if not, write to the Free Software Foundation, 00023 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00024 * 00025 * @section Description 00026 * 00027 * Address Resolution Protocol is used to determine the hardware address of 00028 * a specific host when only its IPv4 address is known. Refer to RFC 826 00029 * 00030 * @author Oryx Embedded SARL (www.oryx-embedded.com) 00031 * @version 1.7.6 00032 **/ 00033 00034 //Switch to the appropriate trace level 00035 #define TRACE_LEVEL ARP_TRACE_LEVEL 00036 00037 //Dependencies 00038 #include <string.h> 00039 #include "core/net.h" 00040 #include "core/ethernet.h" 00041 #include "ipv4/arp.h" 00042 #include "debug.h" 00043 00044 //Check TCP/IP stack configuration 00045 #if (IPV4_SUPPORT == ENABLED && ETH_SUPPORT == ENABLED) 00046 00047 //Tick counter to handle periodic operations 00048 systime_t arpTickCounter; 00049 00050 00051 /** 00052 * @brief ARP cache initialization 00053 * @param[in] interface Underlying network interface 00054 * @return Error code 00055 **/ 00056 00057 error_t arpInit(NetInterface *interface) 00058 { 00059 //Initialize the ARP cache 00060 memset(interface->arpCache, 0, sizeof(interface->arpCache)); 00061 00062 //Successful initialization 00063 return NO_ERROR; 00064 } 00065 00066 00067 /** 00068 * @brief Flush ARP cache 00069 * @param[in] interface Underlying network interface 00070 **/ 00071 00072 void arpFlushCache(NetInterface *interface) 00073 { 00074 uint_t i; 00075 ArpCacheEntry *entry; 00076 00077 //Loop through ARP cache entries 00078 for(i = 0; i < ARP_CACHE_SIZE; i++) 00079 { 00080 //Point to the current entry 00081 entry = &interface->arpCache[i]; 00082 00083 //Drop packets that are waiting for address resolution 00084 arpFlushQueuedPackets(interface, entry); 00085 //Release ARP entry 00086 entry->state = ARP_STATE_NONE; 00087 } 00088 } 00089 00090 00091 /** 00092 * @brief Create a new entry in the ARP cache 00093 * @param[in] interface Underlying network interface 00094 * @return Pointer to the newly created entry 00095 **/ 00096 00097 ArpCacheEntry *arpCreateEntry(NetInterface *interface) 00098 { 00099 uint_t i; 00100 ArpCacheEntry *entry; 00101 ArpCacheEntry *oldestEntry; 00102 00103 //Keep track of the oldest entry 00104 oldestEntry = &interface->arpCache[0]; 00105 00106 //Loop through ARP cache entries 00107 for(i = 0; i < ARP_CACHE_SIZE; i++) 00108 { 00109 //Point to the current entry 00110 entry = &interface->arpCache[i]; 00111 00112 //Check whether the entry is currently in used or not 00113 if(entry->state == ARP_STATE_NONE) 00114 { 00115 //Erase contents 00116 memset(entry, 0, sizeof(ArpCacheEntry)); 00117 //Return a pointer to the ARP entry 00118 return entry; 00119 } 00120 00121 //Keep track of the oldest entry in the table 00122 if(timeCompare(entry->timestamp, oldestEntry->timestamp) < 0) 00123 oldestEntry = entry; 00124 } 00125 00126 //Drop any pending packets 00127 arpFlushQueuedPackets(interface, oldestEntry); 00128 //The oldest entry is removed whenever the table runs out of space 00129 memset(oldestEntry, 0, sizeof(ArpCacheEntry)); 00130 //Return a pointer to the ARP entry 00131 return oldestEntry; 00132 } 00133 00134 00135 /** 00136 * @brief Search the ARP cache for a given IPv4 address 00137 * @param[in] interface Underlying network interface 00138 * @param[in] ipAddr IPv4 address 00139 * @return A pointer to the matching ARP entry is returned. NULL is returned 00140 * if the specified IPv4 address could not be found in ARP cache 00141 **/ 00142 00143 ArpCacheEntry *arpFindEntry(NetInterface *interface, Ipv4Addr ipAddr) 00144 { 00145 uint_t i; 00146 ArpCacheEntry *entry; 00147 00148 //Loop through ARP cache entries 00149 for(i = 0; i < ARP_CACHE_SIZE; i++) 00150 { 00151 //Point to the current entry 00152 entry = &interface->arpCache[i]; 00153 00154 //Check whether the entry is currently in used 00155 if(entry->state != ARP_STATE_NONE) 00156 { 00157 //Current entry matches the specified address? 00158 if(entry->ipAddr == ipAddr) 00159 return entry; 00160 } 00161 } 00162 00163 //No matching entry in ARP cache... 00164 return NULL; 00165 } 00166 00167 00168 /** 00169 * @brief Send packets that are waiting for address resolution 00170 * @param[in] interface Underlying network interface 00171 * @param[in] entry Pointer to a ARP cache entry 00172 **/ 00173 00174 void arpSendQueuedPackets(NetInterface *interface, ArpCacheEntry *entry) 00175 { 00176 uint_t i; 00177 ArpQueueItem *item; 00178 00179 //Check current state 00180 if(entry->state == ARP_STATE_INCOMPLETE) 00181 { 00182 //Loop through the queued packets 00183 for(i = 0; i < entry->queueSize; i++) 00184 { 00185 //Point to the current queue item 00186 item = &entry->queue[i]; 00187 00188 //Send the IPv4 packet 00189 ethSendFrame(interface, &entry->macAddr, 00190 item->buffer, item->offset, ETH_TYPE_IPV4); 00191 00192 //Release memory buffer 00193 netBufferFree(item->buffer); 00194 } 00195 } 00196 00197 //The queue is now empty 00198 entry->queueSize = 0; 00199 } 00200 00201 00202 /** 00203 * @brief Flush packet queue 00204 * @param[in] interface Underlying network interface 00205 * @param[in] entry Pointer to a ARP cache entry 00206 **/ 00207 00208 void arpFlushQueuedPackets(NetInterface *interface, ArpCacheEntry *entry) 00209 { 00210 uint_t i; 00211 00212 //Check current state 00213 if(entry->state == ARP_STATE_INCOMPLETE) 00214 { 00215 //Drop packets that are waiting for address resolution 00216 for(i = 0; i < entry->queueSize; i++) 00217 { 00218 //Release memory buffer 00219 netBufferFree(entry->queue[i].buffer); 00220 } 00221 } 00222 00223 //The queue is now empty 00224 entry->queueSize = 0; 00225 } 00226 00227 00228 /** 00229 * @brief Address resolution using ARP protocol 00230 * @param[in] interface Underlying network interface 00231 * @param[in] ipAddr IPv4 address 00232 * @param[in] macAddr Physical address matching the specified IPv4 address 00233 * @return Error code 00234 **/ 00235 00236 error_t arpResolve(NetInterface *interface, Ipv4Addr ipAddr, MacAddr *macAddr) 00237 { 00238 error_t error; 00239 ArpCacheEntry *entry; 00240 00241 //Search the ARP cache for the specified IPv4 address 00242 entry = arpFindEntry(interface, ipAddr); 00243 00244 //Check whether a matching entry has been found 00245 if(entry != NULL) 00246 { 00247 //Check the state of the ARP entry 00248 if(entry->state == ARP_STATE_INCOMPLETE) 00249 { 00250 //The address resolution is already in progress 00251 error = ERROR_IN_PROGRESS; 00252 } 00253 else if(entry->state == ARP_STATE_STALE) 00254 { 00255 //Copy the MAC address associated with the specified IPv4 address 00256 *macAddr = entry->macAddr; 00257 00258 //Start delay timer 00259 entry->timestamp = osGetSystemTime(); 00260 //Delay before sending the first probe 00261 entry->timeout = ARP_DELAY_FIRST_PROBE_TIME; 00262 //Switch to the DELAY state 00263 entry->state = ARP_STATE_DELAY; 00264 00265 //Successful address resolution 00266 error = NO_ERROR; 00267 } 00268 else 00269 { 00270 //Copy the MAC address associated with the specified IPv4 address 00271 *macAddr = entry->macAddr; 00272 00273 //Successful address resolution 00274 error = NO_ERROR; 00275 } 00276 } 00277 else 00278 { 00279 //If no entry exists, then create a new one 00280 entry = arpCreateEntry(interface); 00281 00282 //ARP cache entry successfully created? 00283 if(entry != NULL) 00284 { 00285 //Record the IPv4 address whose MAC address is unknown 00286 entry->ipAddr = ipAddr; 00287 00288 //Reset retransmission counter 00289 entry->retransmitCount = 0; 00290 //No packet are pending in the transmit queue 00291 entry->queueSize = 0; 00292 00293 //Send an ARP request 00294 arpSendRequest(interface, entry->ipAddr, &MAC_BROADCAST_ADDR); 00295 00296 //Save the time at which the packet was sent 00297 entry->timestamp = osGetSystemTime(); 00298 //Set timeout value 00299 entry->timeout = ARP_REQUEST_TIMEOUT; 00300 //Enter INCOMPLETE state 00301 entry->state = ARP_STATE_INCOMPLETE; 00302 00303 //The address resolution is in progress 00304 error = ERROR_IN_PROGRESS; 00305 } 00306 else 00307 { 00308 //Failed to create ARP cache entry... 00309 error = ERROR_OUT_OF_RESOURCES; 00310 } 00311 } 00312 00313 //Return status code 00314 return error; 00315 } 00316 00317 00318 /** 00319 * @brief Enqueue an IPv4 packet waiting for address resolution 00320 * @param[in] interface Underlying network interface 00321 * @param[in] ipAddr IPv4 address of the destination host 00322 * @param[in] buffer Multi-part buffer containing the packet to be enqueued 00323 * @param[in] offset Offset to the first byte of the packet 00324 * @return Error code 00325 **/ 00326 00327 error_t arpEnqueuePacket(NetInterface *interface, 00328 Ipv4Addr ipAddr, NetBuffer *buffer, size_t offset) 00329 { 00330 error_t error; 00331 uint_t i; 00332 size_t length; 00333 ArpCacheEntry *entry; 00334 00335 //Retrieve the length of the multi-part buffer 00336 length = netBufferGetLength(buffer); 00337 00338 //Search the ARP cache for the specified IPv4 address 00339 entry = arpFindEntry(interface, ipAddr); 00340 00341 //Check whether a matching entry exists 00342 if(entry != NULL) 00343 { 00344 //Check current state 00345 if(entry->state == ARP_STATE_INCOMPLETE) 00346 { 00347 //Check whether the packet queue is full 00348 if(entry->queueSize >= ARP_MAX_PENDING_PACKETS) 00349 { 00350 //When the queue overflows, the new arrival should replace the oldest entry 00351 netBufferFree(entry->queue[0].buffer); 00352 00353 //Make room for the new packet 00354 for(i = 1; i < ARP_MAX_PENDING_PACKETS; i++) 00355 entry->queue[i - 1] = entry->queue[i]; 00356 00357 //Adjust the number of pending packets 00358 entry->queueSize--; 00359 } 00360 00361 //Index of the entry to be filled in 00362 i = entry->queueSize; 00363 //Allocate a memory buffer to store the packet 00364 entry->queue[i].buffer = netBufferAlloc(length); 00365 00366 //Successful memory allocation? 00367 if(entry->queue[i].buffer != NULL) 00368 { 00369 //Copy the contents of the IPv4 packet 00370 netBufferCopy(entry->queue[i].buffer, 0, buffer, 0, length); 00371 //Offset to the first byte of the IPv4 header 00372 entry->queue[i].offset = offset; 00373 00374 //Increment the number of queued packets 00375 entry->queueSize++; 00376 //The packet was successfully enqueued 00377 error = NO_ERROR; 00378 } 00379 else 00380 { 00381 //Failed to allocate memory 00382 error = ERROR_OUT_OF_MEMORY; 00383 } 00384 } 00385 else 00386 { 00387 //The address is already resolved 00388 error = ERROR_UNEXPECTED_STATE; 00389 } 00390 } 00391 else 00392 { 00393 //No matching entry in ARP cache 00394 error = ERROR_NOT_FOUND; 00395 } 00396 00397 //Return status code 00398 return error; 00399 } 00400 00401 00402 /** 00403 * @brief ARP timer handler 00404 * 00405 * This routine must be periodically called by the TCP/IP stack to 00406 * manage ARP cache 00407 * 00408 * @param[in] interface Underlying network interface 00409 **/ 00410 00411 void arpTick(NetInterface *interface) 00412 { 00413 uint_t i; 00414 systime_t time; 00415 ArpCacheEntry *entry; 00416 00417 //Get current time 00418 time = osGetSystemTime(); 00419 00420 //Go through ARP cache 00421 for(i = 0; i < ARP_CACHE_SIZE; i++) 00422 { 00423 //Point to the current entry 00424 entry = &interface->arpCache[i]; 00425 00426 //INCOMPLETE state? 00427 if(entry->state == ARP_STATE_INCOMPLETE) 00428 { 00429 //The request timed out? 00430 if(timeCompare(time, entry->timestamp + entry->timeout) >= 0) 00431 { 00432 //Increment retransmission counter 00433 entry->retransmitCount++; 00434 00435 //Check whether the maximum number of retransmissions has been exceeded 00436 if(entry->retransmitCount < ARP_MAX_REQUESTS) 00437 { 00438 //Retransmit ARP request 00439 arpSendRequest(interface, entry->ipAddr, &MAC_BROADCAST_ADDR); 00440 00441 //Save the time at which the packet was sent 00442 entry->timestamp = time; 00443 //Set timeout value 00444 entry->timeout = ARP_REQUEST_TIMEOUT; 00445 } 00446 else 00447 { 00448 //Drop packets that are waiting for address resolution 00449 arpFlushQueuedPackets(interface, entry); 00450 //The entry should be deleted since address resolution has failed 00451 entry->state = ARP_STATE_NONE; 00452 } 00453 } 00454 } 00455 //REACHABLE state? 00456 else if(entry->state == ARP_STATE_REACHABLE) 00457 { 00458 //Periodically time out ARP cache entries 00459 if(timeCompare(time, entry->timestamp + entry->timeout) >= 0) 00460 { 00461 //Save current time 00462 entry->timestamp = osGetSystemTime(); 00463 //Enter STALE state 00464 entry->state = ARP_STATE_STALE; 00465 } 00466 } 00467 //DELAY state? 00468 else if(entry->state == ARP_STATE_DELAY) 00469 { 00470 //Wait for the specified delay before sending the first probe 00471 if(timeCompare(time, entry->timestamp + entry->timeout) >= 0) 00472 { 00473 //Send a point-to-point ARP request to the host 00474 arpSendRequest(interface, entry->ipAddr, &entry->macAddr); 00475 00476 //Save the time at which the packet was sent 00477 entry->timestamp = time; 00478 //Set timeout value 00479 entry->timeout = ARP_PROBE_TIMEOUT; 00480 //Switch to the PROBE state 00481 entry->state = ARP_STATE_PROBE; 00482 } 00483 } 00484 //PROBE state? 00485 else if(entry->state == ARP_STATE_PROBE) 00486 { 00487 //The request timed out? 00488 if(timeCompare(time, entry->timestamp + entry->timeout) >= 0) 00489 { 00490 //Increment retransmission counter 00491 entry->retransmitCount++; 00492 00493 //Check whether the maximum number of retransmissions has been exceeded 00494 if(entry->retransmitCount < ARP_MAX_PROBES) 00495 { 00496 //Send a point-to-point ARP request to the host 00497 arpSendRequest(interface, entry->ipAddr, &entry->macAddr); 00498 00499 //Save the time at which the packet was sent 00500 entry->timestamp = time; 00501 //Set timeout value 00502 entry->timeout = ARP_PROBE_TIMEOUT; 00503 } 00504 else 00505 { 00506 //The entry should be deleted since the host is not reachable anymore 00507 entry->state = ARP_STATE_NONE; 00508 } 00509 } 00510 } 00511 } 00512 } 00513 00514 00515 /** 00516 * @brief Incoming ARP packet processing 00517 * @param[in] interface Underlying network interface 00518 * @param[in] arpPacket Incoming ARP packet 00519 * @param[in] length Packet length 00520 **/ 00521 00522 void arpProcessPacket(NetInterface *interface, ArpPacket *arpPacket, size_t length) 00523 { 00524 //Discard invalid ARP packets 00525 if(length < sizeof(ArpPacket)) 00526 return; 00527 00528 //Debug message 00529 TRACE_INFO("ARP packet received (%" PRIuSIZE " bytes)...\r\n", length); 00530 //Dump ARP packet contents for debugging purpose 00531 arpDumpPacket(arpPacket); 00532 00533 //Make sure the hardware type is valid 00534 if(arpPacket->hrd != HTONS(ARP_HARDWARE_TYPE_ETH)) 00535 return; 00536 //Make sure the protocol type is valid 00537 if(arpPacket->pro != HTONS(ARP_PROTOCOL_TYPE_IPV4)) 00538 return; 00539 //Check the length of the hardware address 00540 if(arpPacket->hln != sizeof(MacAddr)) 00541 return; 00542 //Check the length of the protocol address 00543 if(arpPacket->pln != sizeof(Ipv4Addr)) 00544 return; 00545 00546 //Check the state of the host address 00547 if(interface->ipv4Context.addrState == IPV4_ADDR_STATE_TENTATIVE) 00548 { 00549 //If the host receives any ARP packet where the sender IP address is 00550 //the address being probed for, then this is a conflicting ARP packet 00551 if(arpPacket->spa == interface->ipv4Context.addr) 00552 { 00553 //An address conflict has been detected... 00554 interface->ipv4Context.addrConflict = TRUE; 00555 //Exit immediately 00556 return; 00557 } 00558 } 00559 else if(interface->ipv4Context.addrState == IPV4_ADDR_STATE_VALID) 00560 { 00561 //Check whether the sender protocol address matches the IP 00562 //address assigned to the interface 00563 if(arpPacket->spa == interface->ipv4Context.addr) 00564 { 00565 //If the sender hardware address does not match the hardware 00566 //address of that interface, then this is a conflicting ARP packet 00567 if(!macCompAddr(&arpPacket->sha, &interface->macAddr)) 00568 { 00569 //An address conflict has been detected... 00570 interface->ipv4Context.addrConflict = TRUE; 00571 //Exit immediately 00572 return; 00573 } 00574 } 00575 } 00576 00577 //Check whether the target protocol address matches the IP 00578 //address assigned to the interface 00579 if(arpPacket->tpa != interface->ipv4Context.addr) 00580 return; 00581 00582 //Check operation code 00583 switch(ntohs(arpPacket->op)) 00584 { 00585 //ARP request? 00586 case ARP_OPCODE_ARP_REQUEST: 00587 //Process incoming ARP request 00588 arpProcessRequest(interface, arpPacket); 00589 break; 00590 //ARP reply? 00591 case ARP_OPCODE_ARP_REPLY: 00592 //Process incoming ARP reply 00593 arpProcessReply(interface, arpPacket); 00594 break; 00595 //Unknown operation code? 00596 default: 00597 //Debug message 00598 TRACE_INFO("Unknown operation code!\r\n"); 00599 //Discard incoming packet 00600 break; 00601 } 00602 } 00603 00604 00605 /** 00606 * @brief Incoming ARP request processing 00607 * @param[in] interface Underlying network interface 00608 * @param[in] arpRequest Incoming ARP request 00609 **/ 00610 00611 void arpProcessRequest(NetInterface *interface, ArpPacket *arpRequest) 00612 { 00613 //Debug message 00614 TRACE_INFO("ARP Request received...\r\n"); 00615 00616 //Check sender protocol address 00617 if(ipv4IsBroadcastAddr(interface, arpRequest->spa)) 00618 return; 00619 if(ipv4IsMulticastAddr(arpRequest->spa)) 00620 return; 00621 00622 //Check whether the target IP address is an address being probed for 00623 if(ipv4IsTentativeAddr(interface, arpRequest->tpa)) 00624 { 00625 //ARP probe received? 00626 if(arpRequest->spa == IPV4_UNSPECIFIED_ADDR) 00627 { 00628 //If the sender hardware address does not match the hardware 00629 //address of that interface, then this is a conflicting ARP packet 00630 if(!macCompAddr(&arpRequest->sha, &interface->macAddr)) 00631 { 00632 //An address conflict has been detected... 00633 interface->ipv4Context.addrConflict = TRUE; 00634 } 00635 } 00636 00637 //In all cases, the host must not respond to an ARP request for an 00638 //address being probed for 00639 return; 00640 } 00641 00642 //Send ARP reply 00643 arpSendReply(interface, arpRequest->spa, &arpRequest->sha, &arpRequest->sha); 00644 } 00645 00646 00647 /** 00648 * @brief Incoming ARP reply processing 00649 * @param[in] interface Underlying network interface 00650 * @param[in] arpReply Incoming ARP reply 00651 **/ 00652 00653 void arpProcessReply(NetInterface *interface, ArpPacket *arpReply) 00654 { 00655 ArpCacheEntry *entry; 00656 00657 //Debug message 00658 TRACE_INFO("ARP Reply received...\r\n"); 00659 00660 //Check sender protocol address 00661 if(arpReply->spa == IPV4_UNSPECIFIED_ADDR) 00662 return; 00663 if(ipv4IsBroadcastAddr(interface, arpReply->spa)) 00664 return; 00665 if(ipv4IsMulticastAddr(arpReply->spa)) 00666 return; 00667 00668 //Check sender hardware address 00669 if(macCompAddr(&arpReply->sha, &MAC_UNSPECIFIED_ADDR)) 00670 return; 00671 if(macCompAddr(&arpReply->sha, &MAC_BROADCAST_ADDR)) 00672 return; 00673 if(macIsMulticastAddr(&arpReply->sha)) 00674 return; 00675 00676 //Check whether the target IP address is an address being probed for 00677 if(ipv4IsTentativeAddr(interface, arpReply->tpa)) 00678 return; 00679 00680 //Search the ARP cache for the specified IPv4 address 00681 entry = arpFindEntry(interface, arpReply->spa); 00682 00683 //Check whether a matching entry has been found 00684 if(entry != NULL) 00685 { 00686 //Check current state 00687 if(entry->state == ARP_STATE_INCOMPLETE) 00688 { 00689 //Record the corresponding MAC address 00690 entry->macAddr = arpReply->sha; 00691 00692 //Send all the packets that are pending for transmission 00693 arpSendQueuedPackets(interface, entry); 00694 00695 //Save current time 00696 entry->timestamp = osGetSystemTime(); 00697 //The validity of the ARP entry is limited in time 00698 entry->timeout = ARP_REACHABLE_TIME; 00699 //Switch to the REACHABLE state 00700 entry->state = ARP_STATE_REACHABLE; 00701 } 00702 else if(entry->state == ARP_STATE_REACHABLE) 00703 { 00704 //Different link-layer address than cached? 00705 if(!macCompAddr(&arpReply->sha, &entry->macAddr)) 00706 { 00707 //Enter STALE state 00708 entry->state = ARP_STATE_STALE; 00709 } 00710 } 00711 else if(entry->state == ARP_STATE_PROBE) 00712 { 00713 //Record IPv4/MAC address pair 00714 entry->ipAddr = arpReply->spa; 00715 entry->macAddr = arpReply->sha; 00716 00717 //Save current time 00718 entry->timestamp = osGetSystemTime(); 00719 //The validity of the ARP entry is limited in time 00720 entry->timeout = ARP_REACHABLE_TIME; 00721 //Switch to the REACHABLE state 00722 entry->state = ARP_STATE_REACHABLE; 00723 } 00724 } 00725 } 00726 00727 00728 /** 00729 * @brief Send ARP probe 00730 * @param[in] interface Underlying network interface 00731 * @param[in] targetIpAddr Target IPv4 address 00732 * @return Error code 00733 **/ 00734 00735 error_t arpSendProbe(NetInterface *interface, Ipv4Addr targetIpAddr) 00736 { 00737 error_t error; 00738 size_t offset; 00739 NetBuffer *buffer; 00740 ArpPacket *arpRequest; 00741 00742 //Allocate a memory buffer to hold an ARP packet 00743 buffer = ethAllocBuffer(sizeof(ArpPacket), &offset); 00744 //Failed to allocate buffer? 00745 if(buffer == NULL) 00746 return ERROR_OUT_OF_MEMORY; 00747 00748 //Point to the beginning of the ARP packet 00749 arpRequest = netBufferAt(buffer, offset); 00750 00751 //Format ARP request 00752 arpRequest->hrd = htons(ARP_HARDWARE_TYPE_ETH); 00753 arpRequest->pro = htons(ARP_PROTOCOL_TYPE_IPV4); 00754 arpRequest->hln = sizeof(MacAddr); 00755 arpRequest->pln = sizeof(Ipv4Addr); 00756 arpRequest->op = htons(ARP_OPCODE_ARP_REQUEST); 00757 arpRequest->sha = interface->macAddr; 00758 arpRequest->spa = IPV4_UNSPECIFIED_ADDR; 00759 arpRequest->tha = MAC_UNSPECIFIED_ADDR; 00760 arpRequest->tpa = targetIpAddr; 00761 00762 //Debug message 00763 TRACE_INFO("Sending ARP Probe (%" PRIuSIZE " bytes)...\r\n", sizeof(ArpPacket)); 00764 //Dump ARP packet contents for debugging purpose 00765 arpDumpPacket(arpRequest); 00766 00767 //Send ARP request 00768 error = ethSendFrame(interface, &MAC_BROADCAST_ADDR, 00769 buffer, offset, ETH_TYPE_ARP); 00770 00771 //Free previously allocated memory 00772 netBufferFree(buffer); 00773 //Return status code 00774 return error; 00775 } 00776 00777 00778 /** 00779 * @brief Send ARP request 00780 * @param[in] interface Underlying network interface 00781 * @param[in] targetIpAddr Target IPv4 address 00782 * @param[in] destMacAddr Destination MAC address 00783 * @return Error code 00784 **/ 00785 00786 error_t arpSendRequest(NetInterface *interface, 00787 Ipv4Addr targetIpAddr, const MacAddr *destMacAddr) 00788 { 00789 error_t error; 00790 size_t offset; 00791 NetBuffer *buffer; 00792 ArpPacket *arpRequest; 00793 Ipv4Addr senderIpAddr; 00794 00795 //Select the most appropriate sender IP address to be used 00796 error = ipv4SelectSourceAddr(&interface, targetIpAddr, &senderIpAddr); 00797 //No address assigned to the interface? 00798 if(error) 00799 return error; 00800 00801 //Allocate a memory buffer to hold an ARP packet 00802 buffer = ethAllocBuffer(sizeof(ArpPacket), &offset); 00803 //Failed to allocate buffer? 00804 if(buffer == NULL) 00805 return ERROR_OUT_OF_MEMORY; 00806 00807 //Point to the beginning of the ARP packet 00808 arpRequest = netBufferAt(buffer, offset); 00809 00810 //Format ARP request 00811 arpRequest->hrd = htons(ARP_HARDWARE_TYPE_ETH); 00812 arpRequest->pro = htons(ARP_PROTOCOL_TYPE_IPV4); 00813 arpRequest->hln = sizeof(MacAddr); 00814 arpRequest->pln = sizeof(Ipv4Addr); 00815 arpRequest->op = htons(ARP_OPCODE_ARP_REQUEST); 00816 arpRequest->sha = interface->macAddr; 00817 arpRequest->spa = senderIpAddr; 00818 arpRequest->tha = MAC_UNSPECIFIED_ADDR; 00819 arpRequest->tpa = targetIpAddr; 00820 00821 //Debug message 00822 TRACE_INFO("Sending ARP Request (%" PRIuSIZE " bytes)...\r\n", sizeof(ArpPacket)); 00823 //Dump ARP packet contents for debugging purpose 00824 arpDumpPacket(arpRequest); 00825 00826 //Send ARP request 00827 error = ethSendFrame(interface, destMacAddr, buffer, offset, ETH_TYPE_ARP); 00828 00829 //Free previously allocated memory 00830 netBufferFree(buffer); 00831 //Return status code 00832 return error; 00833 } 00834 00835 00836 /** 00837 * @brief Send ARP reply 00838 * @param[in] interface Underlying network interface 00839 * @param[in] targetIpAddr Target IPv4 address 00840 * @param[in] targetMacAddr Target MAC address 00841 * @param[in] destMacAddr Destination MAC address 00842 * @return Error code 00843 **/ 00844 00845 error_t arpSendReply(NetInterface *interface, Ipv4Addr targetIpAddr, 00846 const MacAddr *targetMacAddr, const MacAddr *destMacAddr) 00847 { 00848 error_t error; 00849 size_t offset; 00850 NetBuffer *buffer; 00851 ArpPacket *arpReply; 00852 00853 //Allocate a memory buffer to hold an ARP packet 00854 buffer = ethAllocBuffer(sizeof(ArpPacket), &offset); 00855 //Failed to allocate buffer? 00856 if(buffer == NULL) 00857 return ERROR_OUT_OF_MEMORY; 00858 00859 //Point to the beginning of the ARP packet 00860 arpReply = netBufferAt(buffer, offset); 00861 00862 //Format ARP reply 00863 arpReply->hrd = htons(ARP_HARDWARE_TYPE_ETH); 00864 arpReply->pro = htons(ETH_TYPE_IPV4); 00865 arpReply->hln = sizeof(MacAddr); 00866 arpReply->pln = sizeof(Ipv4Addr); 00867 arpReply->op = htons(ARP_OPCODE_ARP_REPLY); 00868 arpReply->sha = interface->macAddr; 00869 arpReply->spa = interface->ipv4Context.addr; 00870 arpReply->tha = *targetMacAddr; 00871 arpReply->tpa = targetIpAddr; 00872 00873 //Debug message 00874 TRACE_INFO("Sending ARP Reply (%" PRIuSIZE " bytes)...\r\n", sizeof(ArpPacket)); 00875 //Dump ARP packet contents for debugging purpose 00876 arpDumpPacket(arpReply); 00877 00878 //Send ARP reply 00879 error = ethSendFrame(interface, destMacAddr, buffer, offset, ETH_TYPE_ARP); 00880 00881 //Free previously allocated memory 00882 netBufferFree(buffer); 00883 //Return status code 00884 return error; 00885 } 00886 00887 00888 /** 00889 * @brief Dump ARP packet for debugging purpose 00890 * @param[in] arpPacket ARP header 00891 **/ 00892 00893 void arpDumpPacket(const ArpPacket *arpPacket) 00894 { 00895 //Dump ARP packet contents 00896 TRACE_DEBUG(" Hardware Type (hrd) = 0x%04" PRIX16 "\r\n", ntohs(arpPacket->hrd)); 00897 TRACE_DEBUG(" Protocol Type (pro) = 0x%04" PRIX16 "\r\n", ntohs(arpPacket->pro)); 00898 TRACE_DEBUG(" Hardware Address Length (hln) = %" PRIu8 "\r\n", arpPacket->hln); 00899 TRACE_DEBUG(" Protocol Address Length (pln) = %" PRIu8 "\r\n", arpPacket->pln); 00900 TRACE_DEBUG(" Opcode (op) = %" PRIu16 "\r\n", ntohs(arpPacket->op)); 00901 TRACE_DEBUG(" Sender Hardware Address (sha)= %s\r\n", macAddrToString(&arpPacket->sha, NULL)); 00902 TRACE_DEBUG(" Sender Protocol Address (spa) = %s\r\n", ipv4AddrToString(arpPacket->spa, NULL)); 00903 TRACE_DEBUG(" Target Hardware Address (tha)= %s\r\n", macAddrToString(&arpPacket->tha, NULL)); 00904 TRACE_DEBUG(" Target Protocol Address (tpa) = %s\r\n", ipv4AddrToString(arpPacket->tpa, NULL)); 00905 } 00906 00907 #endif 00908
Generated on Tue Jul 12 2022 17:10:12 by
1.7.2