www.pudn.com > zlIP-8051-rtl8019as.zip > ARP.c
/* * Copyright (c) 2003 Electric Application Laboratory of NAN KAI University * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * * Author: Li Zhanglin* */ #include "..\GloblDef\GloblDef.h" #include "..\TCPIP\TCPIPmem.h" #include "..\TCPIP\IP.h" #include "..\Netif\etherif.h" #include "..\Netif\ARP.h" #include "..\TCPIP\Netif.h" BYTE DT_XDATA EtherAddrAny[ETHER_ADDR_LEN] = {0xff,0xff,0xff,0xff,0xff,0xff}; /* entry table */ struct SARPEntry DT_XDATA ARPTable[ARP_ENTRY_MAX_NUM]; /* arp init */ void ARPInit() REENTRANT_MUL { BYTE i; /* set every unit in arp tabel invalid */ for(i = 0; i < ARP_ENTRY_MAX_NUM; i++) ARPTable[i].time = 0; } /* construct a arp query packet and return it */ struct SMemHead DT_XDATA * ARPQuery(struct SNetIf DT_XDATA *NetIf,IP_ADDR DestIP) REENTRANT_SIG { struct SMemHead DT_XDATA *MemHead; struct SEtherHead DT_XDATA *EtherHead; struct SARPPacket DT_XDATA *ARPPacket; /* allocate a packet mem */ if((MemHead = MemAllocate(sizeof(struct SARPPacket) + sizeof(struct SEtherHead))) == NULL) return NULL; EtherHead = (struct SEtherHead DT_XDATA *)(MemHead->pStart); ARPPacket = (struct SARPPacket DT_XDATA *)(MemHead->pStart + sizeof(struct SEtherHead)); /* fill Ether head */ MemCopy(EtherHead->DestAddr,EtherAddrAny,ETHER_ADDR_LEN); MemCopy(EtherHead->ScrAddr , ((struct SEtherDevice DT_XDATA *)(NetIf->Info))->Addr,ETHER_ADDR_LEN); EtherHead->type = htons(ETHER_TYPE_ARP); /* fill arp head */ ARPPacket->HardWareAddrLen = ARP_HARDWARE_ADDR_LEN_ETHER; ARPPacket->HardwareType = htons(ARP_HARDWARE_TYPE_ETHER); ARPPacket->ProtocolAddrLen = ARP_PROTOCOL_ADDR_LEN_IP; ARPPacket->ProtocolType = htons(ARP_PROTOCOL_TYPE_IP); ARPPacket->type = htons(ARP_TYPE_ARP_REQUEST); /* fill arp content */ ARPPacket->IPDestAddr = DestIP; ARPPacket->IPScrAddr = NetIf->IPAddr; MemCopy(ARPPacket->EtherDestAddr,EtherAddrAny,ETHER_ADDR_LEN); MemCopy(ARPPacket->EtherScrAddr, ((struct SEtherDevice DT_XDATA *)(NetIf->Info))->Addr,ETHER_ADDR_LEN); return MemHead; } /* deel with a input arp packet. if send a reply is needed return this replay packet, oterhwise return NULL */ struct SMemHead DT_XDATA *ARPInput(struct SMemHead DT_XDATA *MemHead, struct SNetIf DT_XDATA *NetIf) REENTRANT_MUL { struct SEtherHead DT_XDATA *EtherHead; struct SARPPacket DT_XDATA *ARPPacket; EtherHead = (struct SEtherHead DT_XDATA *)(MemHead->pStart); ARPPacket = (struct SARPPacket DT_XDATA *)(MemHead->pStart + sizeof(struct SEtherHead)); /* which type of arp */ switch(ntohs(ARPPacket->type)) { case ARP_TYPE_ARP_REQUEST: /* if arp request to local host */ if(ARPPacket->IPDestAddr == NetIf->IPAddr) { /* send arp replay */ /* fill Ether head */ MemCopy(EtherHead->DestAddr,ARPPacket->EtherScrAddr,ETHER_ADDR_LEN); MemCopy(EtherHead->ScrAddr, ((struct SEtherDevice DT_XDATA *)(NetIf->Info))->Addr,ETHER_ADDR_LEN); EtherHead->type = htons(ETHER_TYPE_ARP); /* copy source part to dest part. include Ether addr and Ip addr */ MemCopy(ARPPacket->EtherDestAddr,ARPPacket->EtherScrAddr, (sizeof(IP_ADDR) + ETHER_ADDR_LEN)); /* fill source part. include Ether addr and Ip addr*/ ARPPacket->IPScrAddr = NetIf->IPAddr; MemCopy(ARPPacket->EtherScrAddr, ((struct SEtherDevice DT_XDATA *)(NetIf->Info))->Addr,ETHER_ADDR_LEN); /* arp type */ ARPPacket->type = htons(ARP_TYPE_ARP_REPLY); return MemHead; } break; case ARP_TYPE_ARP_REPLY: /* add to arp table */ ARPAddEntry(ARPPacket); break; } /* for any case except ARP_TYPE_ARP_REQUEST for this IP, arp packet is released */ MemFree(MemHead); /* no packet need send */ return NULL; } /* add a entry to arp table */ void ARPAddEntry(struct SARPPacket DT_XDATA *ARPPacket) REENTRANT_MUL { BYTE i; WORD MinTime; BYTE iToReplace; /* index of entry going to be replace */ /* find a free entry */ for(i = 0; i ARPTable[i].time) { MinTime = ARPTable[i].time; iToReplace = i; } } } /* replace the entry */ MemCopy(ARPTable[iToReplace].EtherAddr,ARPPacket->EtherScrAddr, ETHER_ADDR_LEN); ARPTable[iToReplace].IPAddr = ARPPacket->IPScrAddr; /* start timer */ ARPTable[iToReplace].time = ARP_ENTRY_TIME_OUT; } /* find IPAddr in arptable copy it to EtherAddr. if can't find return false */ BOOL ARPFind(BYTE EtherAddr[],IP_ADDR IPAddr) REENTRANT_SIG { BYTE i; for(i = 0; i