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

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

Generated on Sun Oct 29 03:41:07 2006 for Procyon AVRlib by  doxygen 1.4.2