Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
arp.c
Go to the documentation of this file.
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
