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