/***************************************************************************** Function: bool ARPProcess(void) Summary: Processes an incoming ARP packet. Description: Retrieves an ARP packet from the MAC buffer and determines if it is a response to our request (in which case the ARP is resolved) or if it is a request requiring our response (in which case we transmit one.) Precondition: ARP packet is ready in the MAC buffer. Parameters: None Return Values: true - All processing of this ARP packet is complete. Do not call again until a new ARP packet is waiting in the RX buffer. false - This function must be called again. More time is needed to send an ARP response. ***************************************************************************/ bool ARPProcess(void) { ARP_PACKET packet; static NODE_INFO Target; #if defined(STACK_USE_AUTO_IP) uint8_t i; #endif static enum { SM_ARP_IDLE = 0, SM_ARP_REPLY } smARP = SM_ARP_IDLE; switch(smARP) { case SM_ARP_IDLE: // Obtain the incoming ARP packet MACGetArray((uint8_t*)&packet, sizeof(packet)); MACDiscardRx(); SwapARPPacket(&packet); // Validate the ARP packet if ( packet.HardwareType != HW_ETHERNET || packet.MACAddrLen != sizeof(MAC_ADDR) || packet.ProtocolLen != sizeof(IP_ADDR) ) { return true; } #ifdef STACK_USE_ZEROCONF_LINK_LOCAL ARPProcessRxPkt(&packet); #endif #ifdef STACK_USE_AUTO_IP if (packet.SenderIPAddr.Val == AppConfig.MyIPAddr.Val) { AutoIPConflict(0); return true; } #endif // Handle incoming ARP responses #ifdef STACK_CLIENT_MODE if(packet.Operation == ARP_OPERATION_RESP) { /* #if defined(STACK_USE_AUTO_IP) for (i = 0; i < NETWORK_INTERFACES; i++) if (AutoIPConfigIsInProgress(i)) AutoIPConflict(i); #endif*/ Cache.MACAddr = packet.SenderMACAddr; Cache.IPAddr = packet.SenderIPAddr; //putsUART("ARPProcess: SM_ARP_IDLE: ARP_OPERATION_RESP \r\n"); return true; } #endif // Handle incoming ARP requests for our MAC address if(packet.Operation == ARP_OPERATION_REQ) { if(packet.TargetIPAddr.Val != AppConfig.MyIPAddr.Val) { return true; } #ifdef STACK_USE_ZEROCONF_LINK_LOCAL /* Fix for Loop-Back suppression: * For ZCLL-Claim packets, host should not respond. * Check Sender's MAC-address with own MAC-address and * if it is matched, response will not be sent back. This * was leading to flooding of ARP-answeres */ if(!memcmp (&packet.SenderMACAddr, &AppConfig.MyMACAddr, 6)) { putsUART("Loopback answer suppressed \r\n"); return true; } #endif #if defined(STACK_USE_AUTO_IP) for (i = 0; i < NETWORK_INTERFACES; i++) if (AutoIPConfigIsInProgress(i)) { AutoIPConflict(i); return true; } #endif Target.IPAddr = packet.SenderIPAddr; Target.MACAddr = packet.SenderMACAddr; //putsUART("ARPProcess: SM_ARP_IDLE: ARP_OPERATION_REQ \r\n"); smARP = SM_ARP_REPLY; } // Do not break. If we get down here, we need to send a reply. case SM_ARP_REPLY: packet.Operation = ARP_OPERATION_RESP; #if defined(STACK_USE_AUTO_IP) if (AutoIPIsConfigured(0)) { packet.TargetMACAddr.v[0] = 0xFF; packet.TargetMACAddr.v[1] = 0xFF; packet.TargetMACAddr.v[2] = 0xFF; packet.TargetMACAddr.v[3] = 0xFF; packet.TargetMACAddr.v[4] = 0xFF; packet.TargetMACAddr.v[5] = 0xFF; } else #endif packet.TargetMACAddr = Target.MACAddr; packet.TargetIPAddr = Target.IPAddr; #ifdef STACK_USE_ZEROCONF_LINK_LOCAL packet.SenderIPAddr = AppConfig.MyIPAddr; #endif //putsUART("ARPProcess: SM_ARP_REPLY \r\n"); // Send an ARP response to a previously received request if(!ARPPut(&packet)) { return false; } // Begin listening for ARP requests again smARP = SM_ARP_IDLE; break; } return true; }
/***************************************************************************** Function: ARP_RESULT ARPProcess(NET_CONFIG* pIf) Summary: Processes an incoming ARP packet. Description: Retrieves an ARP packet from the MAC buffer and determines if it is a response to our request (in which case the ARP is resolved) or if it is a request requiring our response (in which case we transmit one.) Precondition: ARP packet is ready in the MAC buffer. Parameters: None Return Values: ARP_RES_OK - processing OK. ARP_RES_error - some error occurred ***************************************************************************/ ARP_RESULT ARPProcess(NET_CONFIG* pIf) { ARP_PACKET packet; MAC_ADDR *dstMAC; OA_HASH_ENTRY *hE; ARP_CACHE_DCPT *pArpDcpt; int netIx; TCPIP_MAC_HANDLE hMac; ARP_RESULT arpReqRes; netIx = _TCPIPStackNetIx(pIf); pArpDcpt = arpCache + netIx; hMac = _TCPIPStackNetToMac(pIf); // Obtain the incoming ARP packet and process MACGetArray(hMac, (uint8_t*)&packet, sizeof(packet)); MACDiscardRx(hMac); SwapARPPacket(&packet); // Validate the ARP packet if ( packet.HardwareType != HW_ETHERNET || packet.MACAddrLen != sizeof(MAC_ADDR) || packet.ProtocolLen != sizeof(IP_ADDR) ) { return ARP_RES_OK; } #ifdef TCPIP_STACK_USE_ZEROCONF_LINK_LOCAL ARPProcessRxPkt(pIf, &packet); #endif arpReqRes = ARP_RES_OK; // Handle incoming ARP packet hE = OAHashLookUp(pArpDcpt->cacheDcpt, &packet.SenderIPAddr.Val); if(hE != 0) { // we already have this sender and we should update it _ARPUpdateEntry(pIf, (ARP_HASH_ENTRY*)hE, &packet.SenderMACAddr); } while(packet.TargetIPAddr.Val == pIf->MyIPAddr.Val) { // we are the target and we should add to cache anyway if(hE == 0) { // not there yet arpReqRes = _ARPAddCompleteEntry(pIf, &packet.SenderIPAddr, &packet.SenderMACAddr); } // Handle incoming ARP operation if(packet.Operation == ARP_OPERATION_REQ) { // ARP packet asking for this host IP address #ifdef TCPIP_STACK_USE_ZEROCONF_LINK_LOCAL /* Fix for Loop-Back suppression: * For ZCLL-Claim packets, host should not respond. * Check Sender's MAC-address with own MAC-address and * if it is matched, response will not be sent back. This * was leading to flooding of ARP-answeres */ if(!memcmp (&packet.SenderMACAddr, &pIf->MyMACAddr, 6)) { SYS_CONSOLE_MESSAGE("Loopback answer suppressed \r\n"); break; } #endif #if defined(TCPIP_STACK_USE_AUTO_IP) if ((packet.SenderIPAddr.Val == pIf->MyIPAddr.Val) || AutoIPConfigIsInProgress(pIf)) { AutoIPConflict(pIf); break; } #endif // Need to send a reply to the requestor #if defined(TCPIP_STACK_USE_AUTO_IP) if (AutoIPIsConfigured(pIf)) { dstMAC = &arpBcastAdd; } else #endif { dstMAC = &packet.SenderMACAddr; } // Send an ARP response to the received request if(!ARP_SendIfPkt(pIf, ARP_OPERATION_RESP, (uint32_t)pIf->MyIPAddr.Val, (uint32_t)packet.SenderIPAddr.Val, dstMAC)) { arpReqRes = ARP_RES_TX_FAILED; } } break; } return arpReqRes; }