/*! \file arp.c \brief ARP Protocol Library. */ //***************************************************************************** // // File Name : 'arp.c' // Title : ARP Protocol Library // Author : Pascal Stang // Created : 9/7/2004 // Revised : 7/3/2005 // Version : 0.1 // Target MCU : Atmel AVR series // Editor Tabs : 4 // //***************************************************************************** #include "net.h" #include "nic.h" #include "arp.h" #include "HardwareSerial.h" #ifdef ARP_DEBUG_PRINT #include "debug.h" #include #include "programStrings.h" #include "HardwareSerial.h" #endif // global variables /// Single ARP table entry/record struct ArpEntry { uint32_t ipaddr; ///< remote-note IP address struct netEthAddr ethaddr; ///< remote-node ethernet (hardware/mac) address uint8_t time; ///< time to live (in ARP table); this is decremented by arpTimer() }; struct ArpEntry ArpMyAddr; ///< my local interface information (IP and MAC address) struct ArpEntry ArpTable[ARP_TABLE_SIZE]; ///< ARP table of matched IP<->MAC associations void arpInit(void) { u08 i; // initialize all ArpTable elements to unused for(i=0; iarp ); #endif // for now, we just reply to requests // need to add ARP cache if( (packet->arp.dipaddr == HTONL(ArpMyAddr.ipaddr)) && (packet->arp.opcode == htons(ARP_OPCODE_REQUEST)) ) { // in ARP header // copy sender's address info to dest. fields packet->arp.dhwaddr = packet->arp.shwaddr; packet->arp.dipaddr = packet->arp.sipaddr; // fill in our information packet->arp.shwaddr = ArpMyAddr.ethaddr; packet->arp.sipaddr = HTONL(ArpMyAddr.ipaddr); // change op to reply packet->arp.opcode = htons(ARP_OPCODE_REPLY); // in ethernet header packet->eth.dest = packet->eth.src; packet->eth.src = ArpMyAddr.ethaddr; #ifdef ARP_DEBUG SPrint("Sending ARP Reply\r\n"); arpPrintHeader( &packet->arp ); #endif // send reply! nicSend(len, (unsigned char*)packet); } } void arpIpIn(struct netEthIpHeader* packet) { int8_t index; // check if sender is already present in arp table index = arpMatchIp(HTONL(packet->ip.srcipaddr)); if(index != -1) { // sender's IP address found, update ARP entry ArpTable[index].ethaddr = packet->eth.src; // and we're done return; } // sender was not present in table, // must add in empty/expired slot for(index=0; indexeth.src; ArpTable[index].ipaddr = HTONL(packet->ip.srcipaddr); ArpTable[index].time = ARP_CACHE_TIME_TO_LIVE; // and we're done return; } } // no space in table, we give up } void arpIpOut(struct netEthIpHeader* packet, uint32_t phyDstIp) { int index; // check if destination is already present in arp table // use the physical dstIp if it's provided, otherwise the dstIp in packet if(phyDstIp) index = arpMatchIp(phyDstIp); else index = arpMatchIp(HTONL(packet->ip.destipaddr)); // fill in ethernet info if(index != -1) { // ARP entry present, fill eth address(es) packet->eth.src = ArpMyAddr.ethaddr; packet->eth.dest = ArpTable[index].ethaddr; packet->eth.type = HTONS(ETHTYPE_IP); } else { // not in table, must send ARP request packet->eth.src = ArpMyAddr.ethaddr; // MUST CHANGE, but for now, send this one broadcast packet->eth.dest.addr[0] = 0xFF; packet->eth.dest.addr[1] = 0xFF; packet->eth.dest.addr[2] = 0xFF; packet->eth.dest.addr[3] = 0xFF; packet->eth.dest.addr[4] = 0xFF; packet->eth.dest.addr[5] = 0xFF; packet->eth.type = HTONS(ETHTYPE_IP); } } void arpTimer(void) { int index; // this function meant to be called on a regular time interval // decrement time-to-live for all entries for(index=0; index 6 debugPrintHexTable(60, (unsigned char*)&packet); #endif // print operation type SPrint("Operation : "); if(packet->opcode == htons(ARP_OPCODE_REQUEST)) SPrint("REQUEST"); else if(packet->opcode == htons(ARP_OPCODE_REPLY)) SPrint("REPLY"); else SPrint("UNKNOWN"); Serial.println(); // print source hardware address SPrint("SrcHwAddr : "); netPrintEthAddr(&packet->shwaddr); Serial.println(); // print source protocol address SPrint("SrcProtoAddr: "); netPrintIPAddr(HTONL(packet->sipaddr)); Serial.println(); // print target hardware address SPrint("DstHwAddr : "); netPrintEthAddr(&packet->dhwaddr); Serial.println(); // print target protocol address SPrint("DstProtoAddr: "); netPrintIPAddr(HTONL(packet->dipaddr)); Serial.println(); } void arpPrintTable(void) { uint8_t i; // print ARP table SPrint("Time Eth Address IP Address\r\n"); SPrint("---------------------------------------\r\n"); for(i=0; i