| Line No. | Rev | Author | Line |
|---|---|---|---|
| 1 | 6 | kaklik | /*! \file arp.c \brief ARP Protocol Library. */ |
| 2 | //***************************************************************************** |
||
| 3 | // |
||
| 4 | // File Name : 'arp.c' |
||
| 5 | // Title : ARP Protocol Library |
||
| 6 | // Author : Pascal Stang |
||
| 7 | // Created : 9/7/2004 |
||
| 8 | // Revised : 7/3/2005 |
||
| 9 | // Version : 0.1 |
||
| 10 | // Target MCU : Atmel AVR series |
||
| 11 | // Editor Tabs : 4 |
||
| 12 | // |
||
| 13 | //***************************************************************************** |
||
| 14 | |||
| 15 | #include "global.h" |
||
| 16 | #include "net.h" |
||
| 17 | #include "nic.h" |
||
| 18 | #include "arp.h" |
||
| 19 | |||
| 20 | #include "rprintf.h" |
||
| 21 | |||
| 22 | // global variables |
||
| 23 | |||
| 24 | /// Single ARP table entry/record |
||
| 25 | struct ArpEntry |
||
| 26 | { |
||
| 27 | uint32_t ipaddr; ///< remote-note IP address |
||
| 28 | struct netEthAddr ethaddr; ///< remote-node ethernet (hardware/mac) address |
||
| 29 | uint8_t time; ///< time to live (in ARP table); this is decremented by arpTimer() |
||
| 30 | }; |
||
| 31 | |||
| 32 | struct ArpEntry ArpMyAddr; ///< my local interface information (IP and MAC address) |
||
| 33 | struct ArpEntry ArpTable[ARP_TABLE_SIZE]; ///< ARP table of matched IP<->MAC associations |
||
| 34 | |||
| 35 | |||
| 36 | void arpInit(void) |
||
| 37 | { |
||
| 38 | u08 i; |
||
| 39 | // initialize all ArpTable elements to unused |
||
| 40 | for(i=0; i<ARP_TABLE_SIZE; i++) |
||
| 41 | { |
||
| 42 | ArpTable[i].ipaddr = 0; |
||
| 43 | ArpTable[i].time = 0; |
||
| 44 | } |
||
| 45 | } |
||
| 46 | |||
| 47 | void arpSetAddress(struct netEthAddr* myeth, uint32_t myip) |
||
| 48 | { |
||
| 49 | // set local address record |
||
| 50 | ArpMyAddr.ethaddr = *myeth; |
||
| 51 | ArpMyAddr.ipaddr = myip; |
||
| 52 | } |
||
| 53 | |||
| 54 | void arpArpIn(unsigned int len, struct netEthArpHeader* packet) |
||
| 55 | { |
||
| 56 | #ifdef ARP_DEBUG |
||
| 57 | rprintfProgStrM("Received ARP Request\r\n"); |
||
| 58 | arpPrintHeader( &packet->arp ); |
||
| 59 | #endif |
||
| 60 | |||
| 61 | // for now, we just reply to requests |
||
| 62 | // need to add ARP cache |
||
| 63 | if( (packet->arp.dipaddr == HTONL(ArpMyAddr.ipaddr)) && |
||
| 64 | (packet->arp.opcode == htons(ARP_OPCODE_REQUEST)) ) |
||
| 65 | { |
||
| 66 | // in ARP header |
||
| 67 | // copy sender's address info to dest. fields |
||
| 68 | packet->arp.dhwaddr = packet->arp.shwaddr; |
||
| 69 | packet->arp.dipaddr = packet->arp.sipaddr; |
||
| 70 | // fill in our information |
||
| 71 | packet->arp.shwaddr = ArpMyAddr.ethaddr; |
||
| 72 | packet->arp.sipaddr = HTONL(ArpMyAddr.ipaddr); |
||
| 73 | // change op to reply |
||
| 74 | packet->arp.opcode = htons(ARP_OPCODE_REPLY); |
||
| 75 | |||
| 76 | // in ethernet header |
||
| 77 | packet->eth.dest = packet->eth.src; |
||
| 78 | packet->eth.src = ArpMyAddr.ethaddr; |
||
| 79 | |||
| 80 | #ifdef ARP_DEBUG |
||
| 81 | rprintfProgStrM("Sending ARP Reply\r\n"); |
||
| 82 | arpPrintHeader( &packet->arp ); |
||
| 83 | #endif |
||
| 84 | |||
| 85 | // send reply! |
||
| 86 | nicSend(len, (unsigned char*)packet); |
||
| 87 | } |
||
| 88 | } |
||
| 89 | |||
| 90 | void arpIpIn(struct netEthIpHeader* packet) |
||
| 91 | { |
||
| 92 | int8_t index; |
||
| 93 | |||
| 94 | // check if sender is already present in arp table |
||
| 95 | index = arpMatchIp(HTONL(packet->ip.srcipaddr)); |
||
| 96 | if(index != -1) |
||
| 97 | { |
||
| 98 | // sender's IP address found, update ARP entry |
||
| 99 | ArpTable[index].ethaddr = packet->eth.src; |
||
| 100 | // and we're done |
||
| 101 | return; |
||
| 102 | } |
||
| 103 | |||
| 104 | // sender was not present in table, |
||
| 105 | // must add in empty/expired slot |
||
| 106 | for(index=0; index<ARP_TABLE_SIZE; index++) |
||
| 107 | { |
||
| 108 | if(!ArpTable[index].time) |
||
| 109 | { |
||
| 110 | // write entry |
||
| 111 | ArpTable[index].ethaddr = packet->eth.src; |
||
| 112 | ArpTable[index].ipaddr = HTONL(packet->ip.srcipaddr); |
||
| 113 | ArpTable[index].time = ARP_CACHE_TIME_TO_LIVE; |
||
| 114 | // and we're done |
||
| 115 | return; |
||
| 116 | } |
||
| 117 | } |
||
| 118 | |||
| 119 | // no space in table, we give up |
||
| 120 | } |
||
| 121 | |||
| 122 | void arpIpOut(struct netEthIpHeader* packet, uint32_t phyDstIp) |
||
| 123 | { |
||
| 124 | int index; |
||
| 125 | // check if destination is already present in arp table |
||
| 126 | // use the physical dstIp if it's provided, otherwise the dstIp in packet |
||
| 127 | if(phyDstIp) |
||
| 128 | index = arpMatchIp(phyDstIp); |
||
| 129 | else |
||
| 130 | index = arpMatchIp(HTONL(packet->ip.destipaddr)); |
||
| 131 | // fill in ethernet info |
||
| 132 | if(index != -1) |
||
| 133 | { |
||
| 134 | // ARP entry present, fill eth address(es) |
||
| 135 | packet->eth.src = ArpMyAddr.ethaddr; |
||
| 136 | packet->eth.dest = ArpTable[index].ethaddr; |
||
| 137 | packet->eth.type = HTONS(ETHTYPE_IP); |
||
| 138 | } |
||
| 139 | else |
||
| 140 | { |
||
| 141 | // not in table, must send ARP request |
||
| 142 | packet->eth.src = ArpMyAddr.ethaddr; |
||
| 143 | // MUST CHANGE, but for now, send this one broadcast |
||
| 144 | packet->eth.dest.addr[0] = 0xFF; |
||
| 145 | packet->eth.dest.addr[1] = 0xFF; |
||
| 146 | packet->eth.dest.addr[2] = 0xFF; |
||
| 147 | packet->eth.dest.addr[3] = 0xFF; |
||
| 148 | packet->eth.dest.addr[4] = 0xFF; |
||
| 149 | packet->eth.dest.addr[5] = 0xFF; |
||
| 150 | packet->eth.type = HTONS(ETHTYPE_IP); |
||
| 151 | } |
||
| 152 | } |
||
| 153 | |||
| 154 | void arpTimer(void) |
||
| 155 | { |
||
| 156 | int index; |
||
| 157 | // this function meant to be called on a regular time interval |
||
| 158 | |||
| 159 | // decrement time-to-live for all entries |
||
| 160 | for(index=0; index<ARP_TABLE_SIZE; index++) |
||
| 161 | { |
||
| 162 | if(ArpTable[index].time) |
||
| 163 | ArpTable[index].time--; |
||
| 164 | } |
||
| 165 | } |
||
| 166 | |||
| 167 | int arpMatchIp(uint32_t ipaddr) |
||
| 168 | { |
||
| 169 | uint8_t i; |
||
| 170 | |||
| 171 | // check if IP address is present in arp table |
||
| 172 | for(i=0; i<ARP_TABLE_SIZE; i++) |
||
| 173 | { |
||
| 174 | if(ArpTable[i].ipaddr == ipaddr) |
||
| 175 | { |
||
| 176 | // IP address found |
||
| 177 | return i; |
||
| 178 | } |
||
| 179 | } |
||
| 180 | |||
| 181 | // no match |
||
| 182 | return -1; |
||
| 183 | } |
||
| 184 | |||
| 185 | #ifdef ARP_DEBUG_PRINT |
||
| 186 | void arpPrintHeader(struct netArpHeader* packet) |
||
| 187 | { |
||
| 188 | rprintfProgStrM("ARP Packet:\r\n"); |
||
| 189 | //debugPrintHexTable(60, (unsigned char*)&packet); |
||
| 190 | // print operation type |
||
| 191 | rprintfProgStrM("Operation : "); |
||
| 192 | if(packet->opcode == htons(ARP_OPCODE_REQUEST)) |
||
| 193 | rprintfProgStrM("REQUEST"); |
||
| 194 | else if(packet->opcode == htons(ARP_OPCODE_REPLY)) |
||
| 195 | rprintfProgStrM("REPLY"); |
||
| 196 | else |
||
| 197 | rprintfProgStrM("UNKNOWN"); |
||
| 198 | rprintfCRLF(); |
||
| 199 | // print source hardware address |
||
| 200 | rprintfProgStrM("SrcHwAddr : "); netPrintEthAddr(&packet->shwaddr); rprintfCRLF(); |
||
| 201 | // print source protocol address |
||
| 202 | rprintfProgStrM("SrcProtoAddr: "); netPrintIPAddr(HTONL(packet->sipaddr)); rprintfCRLF(); |
||
| 203 | // print target hardware address |
||
| 204 | rprintfProgStrM("DstHwAddr : "); netPrintEthAddr(&packet->dhwaddr); rprintfCRLF(); |
||
| 205 | // print target protocol address |
||
| 206 | rprintfProgStrM("DstProtoAddr: "); netPrintIPAddr(HTONL(packet->dipaddr)); rprintfCRLF(); |
||
| 207 | } |
||
| 208 | |||
| 209 | |||
| 210 | void arpPrintTable(void) |
||
| 211 | { |
||
| 212 | uint8_t i; |
||
| 213 | |||
| 214 | // print ARP table |
||
| 215 | rprintfProgStrM("Time Eth Address IP Address\r\n"); |
||
| 216 | rprintfProgStrM("---------------------------------------\r\n"); |
||
| 217 | for(i=0; i<ARP_TABLE_SIZE; i++) |
||
| 218 | { |
||
| 219 | rprintfu08(ArpTable[i].time); |
||
| 220 | rprintfProgStrM(" "); |
||
| 221 | netPrintEthAddr(&ArpTable[i].ethaddr); |
||
| 222 | rprintfProgStrM(" "); |
||
| 223 | netPrintIPAddr(ArpTable[i].ipaddr); |
||
| 224 | rprintfCRLF(); |
||
| 225 | } |
||
| 226 | } |
||
| 227 | #endif |
Powered by WebSVN v2.8.3