Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals

arp.c

Go to the documentation of this file.
00001 /*! \file arp.c \brief ARP Protocol Library. */
00002 //*****************************************************************************
00003 //
00004 // File Name    : 'arp.c'
00005 // Title        : ARP Protocol Library
00006 // Author       : Pascal Stang
00007 // Created      : 9/7/2004
00008 // Revised      : 7/3/2005
00009 // Version      : 0.1
00010 // Target MCU   : Atmel AVR series
00011 // Editor Tabs  : 4
00012 //
00013 //*****************************************************************************
00014 
00015 #include "global.h"
00016 #include "net.h"
00017 #include "nic.h"
00018 #include "arp.h"
00019 
00020 #include "rprintf.h"
00021 
00022 // global variables
00023 
00024 struct ArpEntry
00025 {
00026     uint32_t ipaddr;            //< remote-note IP address
00027     struct netEthAddr ethaddr;  //< remote-node ethernet (hardware/mac) address
00028     uint8_t time;               //< time to live (in ARP table); this is decremented by arpTimer()
00029 };
00030 
00031 struct ArpEntry ArpMyAddr;      //< my local interface information (IP and MAC address)
00032 struct ArpEntry ArpTable[ARP_TABLE_SIZE];
00033 
00034 
00035 void arpInit(void)
00036 {
00037     u08 i;
00038     // initialize all ArpTable elements to unused
00039     for(i=0; i<ARP_TABLE_SIZE; i++)
00040     {
00041         ArpTable[i].ipaddr = 0;
00042         ArpTable[i].time = 0;
00043     }
00044 }
00045 
00046 void arpSetAddress(struct netEthAddr* myeth, uint32_t myip)
00047 {
00048     // set local address record
00049     ArpMyAddr.ethaddr = *myeth;
00050     ArpMyAddr.ipaddr = myip;
00051 }
00052 
00053 void arpArpIn(unsigned int len, struct netEthArpHeader* packet)
00054 {
00055     // for now, we just reply to requests
00056     // need to add ARP cache
00057     if( (packet->arp.dipaddr == HTONL(ArpMyAddr.ipaddr)) &&
00058         (packet->arp.opcode == htons(ARP_OPCODE_REQUEST)) )
00059     {
00060         // in ARP header
00061         // copy sender's address info to dest. fields
00062         packet->arp.dhwaddr = packet->arp.shwaddr;
00063         packet->arp.dipaddr = packet->arp.sipaddr;
00064         // fill in our information
00065         packet->arp.shwaddr = ArpMyAddr.ethaddr;
00066         packet->arp.sipaddr = HTONL(ArpMyAddr.ipaddr);
00067         // change op to reply
00068         packet->arp.opcode = htons(ARP_OPCODE_REPLY);
00069         
00070         // in ethernet header
00071         packet->eth.dest = packet->eth.src;
00072         packet->eth.src  = ArpMyAddr.ethaddr;
00073 
00074         //rprintfProgStrM("Sending ARP Reply\r\n");
00075         //arpPrintHeader( &packet->arp );
00076 
00077         // send reply!
00078         nicSend(len, (unsigned char*)packet);
00079     }
00080 }
00081 
00082 void arpIpIn(struct netEthIpHeader* packet)
00083 {
00084     int8_t index;
00085 
00086     // check if sender is already present in arp table
00087     index = arpMatchIp(HTONL(packet->ip.srcipaddr));
00088     if(index != -1)
00089     {
00090         // sender's IP address found, update ARP entry
00091         ArpTable[index].ethaddr = packet->eth.src;
00092         // and we're done
00093         return;
00094     }
00095 
00096     // sender was not present in table,
00097     // must add in empty/expired slot
00098     for(index=0; index<ARP_TABLE_SIZE; index++)
00099     {
00100         if(!ArpTable[index].time)
00101         {
00102             // write entry
00103             ArpTable[index].ethaddr = packet->eth.src;
00104             ArpTable[index].ipaddr = HTONL(packet->ip.srcipaddr);
00105             ArpTable[index].time = ARP_CACHE_TIME_TO_LIVE;
00106             // and we're done
00107             return;
00108         }
00109     }
00110 
00111     // no space in table, we give up
00112 }
00113 
00114 void arpIpOut(struct netEthIpHeader* packet, uint32_t phyDstIp)
00115 {
00116     int index;
00117     // check if destination is already present in arp table
00118     // use the physical dstIp if it's provided, otherwise the dstIp in packet
00119     if(phyDstIp)
00120         index = arpMatchIp(phyDstIp);
00121     else
00122         index = arpMatchIp(HTONL(packet->ip.destipaddr));
00123     // fill in ethernet info
00124     if(index != -1)
00125     {
00126         // ARP entry present, fill eth address(es)
00127         packet->eth.src  = ArpMyAddr.ethaddr;
00128         packet->eth.dest = ArpTable[index].ethaddr;
00129         packet->eth.type = HTONS(ETHTYPE_IP);
00130     }
00131     else
00132     {
00133         // not in table, must send ARP request
00134         packet->eth.src = ArpMyAddr.ethaddr;
00135         // MUST CHANGE, but for now, send this one broadcast
00136         packet->eth.dest.addr[0] = 0xFF;
00137         packet->eth.dest.addr[1] = 0xFF;
00138         packet->eth.dest.addr[2] = 0xFF;
00139         packet->eth.dest.addr[3] = 0xFF;
00140         packet->eth.dest.addr[4] = 0xFF;
00141         packet->eth.dest.addr[5] = 0xFF;
00142         packet->eth.type = HTONS(ETHTYPE_IP);
00143     }
00144 }
00145 
00146 void arpTimer(void)
00147 {
00148     int index;
00149     // this function meant to be called on a regular time interval
00150 
00151     // decrement time-to-live for all entries
00152     for(index=0; index<ARP_TABLE_SIZE; index++)
00153     {
00154         if(ArpTable[index].time)
00155             ArpTable[index].time--;
00156     }
00157 }
00158 
00159 int arpMatchIp(uint32_t ipaddr)
00160 {
00161     uint8_t i;
00162 
00163     // check if IP address is present in arp table
00164     for(i=0; i<ARP_TABLE_SIZE; i++)
00165     {
00166         if(ArpTable[i].ipaddr == ipaddr)
00167         {
00168             // IP address found
00169             return i;
00170         }
00171     }
00172 
00173     // no match
00174     return -1;
00175 }
00176 
00177 #ifdef ARP_DEBUG_PRINT
00178 void arpPrintHeader(struct netArpHeader* packet)
00179 {
00180     rprintfProgStrM("ARP Packet:\r\n");
00181     //debugPrintHexTable(60, (unsigned char*)&packet);
00182     // print operation type
00183     rprintfProgStrM("Operation   : ");
00184     if(packet->opcode == htons(ARP_OPCODE_REQUEST))
00185         rprintfProgStrM("REQUEST");
00186     else if(packet->opcode == htons(ARP_OPCODE_REPLY))
00187         rprintfProgStrM("REPLY");
00188     else
00189         rprintfProgStrM("UNKNOWN");
00190     rprintfCRLF();
00191     // print source hardware address
00192     rprintfProgStrM("SrcHwAddr   : ");  netPrintEthAddr(&packet->shwaddr);  rprintfCRLF();
00193     // print source protocol address
00194     rprintfProgStrM("SrcProtoAddr: ");  netPrintIPAddr(HTONL(packet->sipaddr)); rprintfCRLF();
00195     // print target hardware address
00196     rprintfProgStrM("DstHwAddr   : ");  netPrintEthAddr(&packet->dhwaddr);  rprintfCRLF();
00197     // print target protocol address
00198     rprintfProgStrM("DstProtoAddr: ");  netPrintIPAddr(HTONL(packet->dipaddr)); rprintfCRLF();
00199 }
00200 
00201 
00202 void arpPrintTable(void)
00203 {
00204     uint8_t i;
00205 
00206     // print ARP table
00207     rprintfProgStrM("Time    Eth Address    IP Address\r\n");
00208     rprintfProgStrM("---------------------------------------\r\n");
00209     for(i=0; i<ARP_TABLE_SIZE; i++)
00210     {
00211         rprintfu08(ArpTable[i].time);
00212         rprintfProgStrM("   ");
00213         netPrintEthAddr(&ArpTable[i].ethaddr);
00214         rprintfProgStrM("  ");
00215         netPrintIPAddr(ArpTable[i].ipaddr);
00216         rprintfCRLF();
00217     }
00218 }
00219 #endif

Generated on Mon Aug 22 04:29:27 2005 for Procyon AVRlib by  doxygen 1.4.2