#include <const.h>
#include <errno.h>
#include <arch/mem.h>
#include <kernel/clock.h>
#include <kernel/console.h>
#include <kernel/kmalloc.h>
#include <kernel/semaphore.h>
#include <kernel/task.h>
#include <net/eth.h>
#include <net/ip.h>
#include <net/network.h>
#include <net/rtl8139.h>
#include <net/arp.h>
Go to the source code of this file.
Defines | |||||||
#define | ARP_TABLE_DIM 10 | ||||||
The ARP cache maximum entries. | |||||||
Functions | |||||||
bool | mac_addr_cmp (uint8_t *m1, uint8_t *m2) | ||||||
Compare two ethernet addresses.
| |||||||
void | arp_add_cache (in_addr_t ip, uint8_t *mac) | ||||||
Insert an address resolution into the ARP cache.
| |||||||
bool | arp_remove_cache (in_addr_t ip) | ||||||
Remove an entry from the ARP cache.
| |||||||
void | arp_reset_cache () | ||||||
Reset the ARP resolution cache. | |||||||
bool | arp_ip_to_eth (uint8_t *eth_addr, in_addr_t ip_addr) | ||||||
Translate from IP address to ethernet address.
| |||||||
void | to_arp_layer (arp_t *packet) | ||||||
Get an ARP packet from the ethernet layer.
| |||||||
int | send_arp_packet (in_addr_t ip_to, const uint8_t *eth_to, uint16_t arp_op) | ||||||
Send an ARP packet to the ethernet layer.
| |||||||
int | recv_arp_packet (arp_t *buf, size_t len) | ||||||
Receive an ARP packet.
| |||||||
void | arp_request (char *ip_dot) | ||||||
Send an ARP request.
| |||||||
Variables | |||||||
uint8_t | eth_bcast [ETH_ADDR_LEN] | ||||||
Broadcast ethernet address. | |||||||
struct { | |||||||
in_addr_t ip | |||||||
uint8_t mac [ETH_ADDR_LEN] | |||||||
uint32_t tickstamp | |||||||
} | arp_table [ARP_TABLE_DIM] | ||||||
ARP cache (here are stored all addresses resolutions IP<->MAC). | |||||||
semaphore_t | arp_mutex | ||||||
ARP cache mutex semaphore. |
Definition in file arp.c.
|
The ARP cache maximum entries.
|
|
Insert an address resolution into the ARP cache.
Definition at line 64 of file arp.c.
00065 { 00066 uint32_t age_max=0, pos_max=0, age, ticks; 00067 int i; 00068 00069 DOWN(&arp_mutex); 00070 00071 // Check if the address is already present // 00072 for(i=0; i<ARP_TABLE_DIM; i++) 00073 { 00074 if ( arp_table[i].ip == ip ) 00075 { 00076 // Address already present => refresh cache // 00077 memcpy(arp_table[i].mac, mac, ETH_ADDR_LEN); 00078 arp_table[i].tickstamp = sys_get_ticks(); 00079 00080 UP(&arp_mutex); 00081 return; 00082 } 00083 } 00084 // Find an empty entry in the table // 00085 for(i=0; i<ARP_TABLE_DIM; i++) 00086 { 00087 if ( arp_table[i].ip == 0 ) 00088 { 00089 // Store the address into the ARP table // 00090 arp_table[i].ip = ip; 00091 memcpy(arp_table[i].mac, mac, ETH_ADDR_LEN); 00092 arp_table[i].tickstamp = sys_get_ticks(); 00093 00094 UP(&arp_mutex); 00095 return; 00096 } 00097 // Calculate the age of this entry // 00098 ticks = sys_get_ticks(); 00099 age = ticks - arp_table[i].tickstamp; 00100 if ( age >= age_max ) 00101 { 00102 age_max = age; 00103 pos_max = i; 00104 } 00105 } 00106 // The ARP table is full => overwrite the oldest entry // 00107 arp_table[pos_max].ip = ip; 00108 memcpy(arp_table[pos_max].mac, mac, ETH_ADDR_LEN); 00109 arp_table[pos_max].tickstamp = sys_get_ticks(); 00110 00111 UP(&arp_mutex); 00112 } |
|
Translate from IP address to ethernet address.
Definition at line 147 of file arp.c.
00148 { 00149 int i; 00150 timeout_t time1, time2; 00151 00152 if ( get_eth_mac_addr()==NULL ) 00153 // Ethernet device is down! // 00154 return(FALSE); 00155 00156 // --- Special addresses --- // 00157 if ( (ip_addr==INADDR_ANY) || (ip_addr==get_host_ip()) ) 00158 { 00159 // Maybe we're asking our MAC address (???) // 00160 memcpy(eth_addr, get_eth_mac_addr(), ETH_ADDR_LEN); 00161 return(TRUE); 00162 } 00163 00164 // Check for a broadcast request // 00165 if ( (ip_addr==get_host_bcast()) || (ip_addr==INADDR_BROADCAST) ) 00166 { 00167 // Broadcast in the current LAN // 00168 memcpy(eth_addr, eth_bcast, ETH_ADDR_LEN); 00169 return(TRUE); 00170 } 00171 // --- End of special addresses --- // 00172 00173 // Search the address into the ARP cache // 00174 DOWN(&arp_mutex); 00175 for(i=0; i<ARP_TABLE_DIM; i++) 00176 { 00177 if ( arp_table[i].ip == ip_addr) 00178 { 00179 // Resolution is found in the cache // 00180 memcpy(eth_addr, arp_table[i].mac, ETH_ADDR_LEN); 00181 00182 UP(&arp_mutex); 00183 return(TRUE); 00184 } 00185 } 00186 UP(&arp_mutex); 00187 00188 // Initialize a timeout to ask who has the ip address // 00189 set_timeout(&time1, 4000); 00190 set_timeout(&time2, 0); 00191 00192 while(TRUE) 00193 { 00194 // Search the address into the ARP cache // 00195 DOWN(&arp_mutex); 00196 for(i=0; i<ARP_TABLE_DIM; i++) 00197 { 00198 if ( arp_table[i].ip == ip_addr) 00199 { 00200 // Resolution is found in the cache // 00201 memcpy(eth_addr, arp_table[i].mac, ETH_ADDR_LEN); 00202 00203 UP(&arp_mutex); 00204 return(TRUE); 00205 } 00206 } 00207 UP(&arp_mutex); 00208 00209 // Resolution not found into the cache // 00210 if ( is_timeout(&time1) ) 00211 { 00212 // In this LAN none has this IP // 00213 return(FALSE); 00214 } 00215 00216 if ( is_timeout(&time2) ) 00217 { 00218 kprintf( "\n\rarp who-has %u.%u.%u.%u tell %u.%u.%u.%u" 00219 " (%02x:%02x:%02x:%02x:%02x:%02x)", 00220 00221 IP_A(ntohl(ip_addr)), 00222 IP_B(ntohl(ip_addr)), 00223 IP_C(ntohl(ip_addr)), 00224 IP_D(ntohl(ip_addr)), 00225 00226 IP_A(ntohl(get_host_ip())), 00227 IP_B(ntohl(get_host_ip())), 00228 IP_C(ntohl(get_host_ip())), 00229 IP_D(ntohl(get_host_ip())), 00230 00231 get_eth_mac_addr()[0], 00232 get_eth_mac_addr()[1], 00233 get_eth_mac_addr()[2], 00234 get_eth_mac_addr()[3], 00235 get_eth_mac_addr()[4], 00236 get_eth_mac_addr()[5] 00237 ); 00238 // Ask in broadcast who has the ip // 00239 send_arp_packet(ip_addr, eth_bcast, ARP_OP_REQUEST); 00240 // Wait 1sec before re-sending the request // 00241 set_timeout(&time2, 1000); 00242 } 00243 idle(); 00244 } 00245 } |
|
Remove an entry from the ARP cache.
Definition at line 117 of file arp.c.
00118 { 00119 int i; 00120 00121 DOWN(&arp_mutex); 00122 00123 for(i=0; i<ARP_TABLE_DIM; i++) 00124 if ( arp_table[i].ip == ip ) 00125 { 00126 arp_table[i].ip = 0; 00127 UP(&arp_mutex); 00128 return(TRUE); 00129 } 00130 00131 // The entry has not been found // 00132 UP(&arp_mutex); 00133 return(FALSE); 00134 } |
|
Send an ARP request.
Definition at line 409 of file arp.c.
00410 { 00411 uint8_t eth[ETH_ADDR_LEN]; 00412 in_addr_t ip; 00413 int i; 00414 00415 // Translate the IP address from numbers-and-dot notation into // 00416 // binary network order byte number. // 00417 if ( !inet_aton(ip_dot, &ip) ) 00418 { 00419 // Not a valid address => dump the ARP cache to stdout // 00420 // TODO: return if the ethernet card is not initialized // 00421 kprintf("\n\rIP address MAC address"); 00422 for(i=0; i<ARP_TABLE_DIM; i++) 00423 { 00424 if ( arp_table[i].ip != 0 ) 00425 { 00426 kprintf("\n\r%u.%u.%u.%u", 00427 IP_A(ntohl(arp_table[i].ip)), 00428 IP_B(ntohl(arp_table[i].ip)), 00429 IP_C(ntohl(arp_table[i].ip)), 00430 IP_D(ntohl(arp_table[i].ip)) 00431 ); 00432 gotoxy(16, -1); 00433 kprintf("%02x:%02x:%02x:%02x:%02x:%02x", 00434 arp_table[i].mac[0], 00435 arp_table[i].mac[1], 00436 arp_table[i].mac[2], 00437 arp_table[i].mac[3], 00438 arp_table[i].mac[4], 00439 arp_table[i].mac[5] 00440 ); 00441 } 00442 } 00443 kprintf("\n\r"); 00444 return; 00445 } 00446 00447 // If a valid address is passed perform the address resolution // 00448 if ( arp_ip_to_eth(eth, ip) ) 00449 kprintf("\n\rarp reply %u.%u.%u.%u is-at %02x:%02x:%02x:%02x:%02x:%02x\n\r", 00450 00451 IP_A(ntohl(ip)), IP_B(ntohl(ip)), 00452 IP_C(ntohl(ip)), IP_D(ntohl(ip)), 00453 00454 eth[0], eth[1], eth[2], 00455 eth[3], eth[4], eth[5] 00456 ); 00457 else 00458 kprintf("\n\rhost unreachable!\n\r"); 00459 } |
|
Reset the ARP resolution cache.
Definition at line 137 of file arp.c.
00138 { 00139 INIT_MUTEX(&arp_mutex); 00140 memset(arp_table, 0, sizeof(arp_table)); 00141 } |
|
Compare two ethernet addresses.
Definition at line 53 of file arp.c.
00054 { 00055 if ( memcmp(m1, m2, ETH_ADDR_LEN)==0 ) 00056 return(TRUE); 00057 else 00058 return(FALSE); 00059 } |
|
Receive an ARP packet.
Definition at line 399 of file arp.c.
00400 { 00401 return( -ENOPROTOOPT ); 00402 } |
|
Send an ARP packet to the ethernet layer.
Definition at line 341 of file arp.c.
00342 { 00343 arp_t *packet; 00344 int tot_len; 00345 uint8_t *mac_addr; 00346 00347 packet = kmalloc(sizeof(arp_t)); 00348 if (packet==NULL) 00349 return(-ENOMEM); 00350 00351 // Create the ARP header // 00352 packet->arp_hard_type = htons(ARPHRD_ETHER); 00353 packet->arp_proto_type = htons(ETH_FRAME_IP); 00354 packet->arp_hard_size = ETH_ADDR_LEN; 00355 packet->arp_proto_size = sizeof(in_addr_t); 00356 packet->arp_op = htons(arp_op); 00357 00358 // Copy the MAC address of this host // 00359 if ( (mac_addr = get_eth_mac_addr()) == NULL ) 00360 // No such device or address! // 00361 return(-ENXIO); 00362 00363 memcpy(packet->arp_eth_source, mac_addr, ETH_ADDR_LEN); 00364 // Copy the IP address of this host // 00365 packet->arp_ip_source = get_host_ip(); 00366 00367 // Set the destination MAC address // 00368 memcpy(packet->arp_eth_dest, eth_to, ETH_ADDR_LEN); 00369 // Set the destination IP // 00370 packet->arp_ip_dest = ip_to; 00371 00372 // Go to the ethernet layer... // 00373 tot_len = send_eth_packet(eth_to, packet, sizeof(arp_t), htons(ETH_FRAME_ARP)); 00374 00375 #ifdef DEBUG 00376 kprintf("\n\r%u bytes sent from ethernet layer", tot_len); 00377 #endif 00378 00379 // Free the memory of the packet // 00380 kfree(packet); 00381 00382 if ( tot_len < 0 ) 00383 // Something wrong from at the ethernet layer // 00384 return(tot_len); 00385 00386 // Well done! // 00387 return(0); 00388 } |
|
Get an ARP packet from the ethernet layer.
Definition at line 249 of file arp.c.
00250 { 00251 #ifdef DEBUG 00252 // Dump the packet contents // 00253 kprintf( 00254 "\n\rhard_type:%04X proto_type:%04X hard_size:%u" 00255 "\n\rproto_size:%u op:%04X" 00256 "\n\rsource=%02x:%02x:%02x:%02x:%02x:%02x (%u.%u.%u.%u)" 00257 "\n\rdest =%02x:%02x:%02x:%02x:%02x:%02x (%u.%u.%u.%u)", 00258 00259 ntohs(packet->arp_hard_type), ntohs(packet->arp_proto_type), packet->arp_hard_size, 00260 packet->arp_proto_size, ntohs(packet->arp_op), 00261 00262 packet->arp_eth_source[0], packet->arp_eth_source[1], packet->arp_eth_source[2], 00263 packet->arp_eth_source[3], packet->arp_eth_source[4], packet->arp_eth_source[5], 00264 00265 IP_A(ntohl(packet->arp_ip_source)), IP_B(ntohl(packet->arp_ip_source)), 00266 IP_C(ntohl(packet->arp_ip_source)), IP_D(ntohl(packet->arp_ip_source)), 00267 00268 packet->arp_eth_dest[0], packet->arp_eth_dest[1], packet->arp_eth_dest[2], 00269 packet->arp_eth_dest[3], packet->arp_eth_dest[4], packet->arp_eth_dest[5], 00270 00271 IP_A(ntohl(packet->arp_ip_dest)), IP_B(ntohl(packet->arp_ip_dest)), 00272 IP_C(ntohl(packet->arp_ip_dest)), IP_D(ntohl(packet->arp_ip_dest)) 00273 ); 00274 00275 kprintf("\n\radding into ARP cache %u.%u.%u.%u", 00276 IP_A(ntohl(packet->arp_ip_source)), 00277 IP_B(ntohl(packet->arp_ip_source)), 00278 IP_C(ntohl(packet->arp_ip_source)), 00279 IP_D(ntohl(packet->arp_ip_source)) 00280 ); 00281 #endif 00282 // Add the address into the ARP cache // 00283 arp_add_cache(packet->arp_ip_source, packet->arp_eth_source); 00284 00285 // Identify the ARP operation // 00286 switch( ntohs(packet->arp_op) ) 00287 { 00288 case ARP_OP_REQUEST: 00289 #ifdef ARP_DEBUG 00290 kprintf("\n\rarp who-has %u.%u.%u.%u tell %u.%u.%u.%u (%02x:%02x:%02x:%02x:%02x:%02x)", 00291 00292 IP_A(ntohl(packet->arp_ip_dest)), IP_B(ntohl(packet->arp_ip_dest)), 00293 IP_C(ntohl(packet->arp_ip_dest)), IP_D(ntohl(packet->arp_ip_dest)), 00294 00295 IP_A(ntohl(packet->arp_ip_source)), IP_B(ntohl(packet->arp_ip_source)), 00296 IP_C(ntohl(packet->arp_ip_source)), IP_D(ntohl(packet->arp_ip_source)), 00297 00298 packet->arp_eth_source[0], packet->arp_eth_source[1], packet->arp_eth_source[2], 00299 packet->arp_eth_source[3], packet->arp_eth_source[4], packet->arp_eth_source[5] 00300 ); 00301 #endif 00302 // Check if we must reply our address to the sender // 00303 if (packet->arp_ip_dest == get_host_ip()) 00304 { 00305 // Send our address resolution // 00306 send_arp_packet( 00307 packet->arp_ip_source, 00308 packet->arp_eth_source, 00309 ARP_OP_REPLY 00310 ); 00311 } 00312 break; 00313 00314 case ARP_OP_REPLY: 00315 #ifdef ARP_DEBUG 00316 // Echo reply received // 00317 kprintf("\n\rarp reply %u.%u.%u.%u is-at %02x:%02x:%02x:%02x:%02x:%02x", 00318 00319 IP_A(ntohl(packet->arp_ip_source)), IP_B(ntohl(packet->arp_ip_source)), 00320 IP_C(ntohl(packet->arp_ip_source)), IP_D(ntohl(packet->arp_ip_source)), 00321 00322 packet->arp_eth_source[0], packet->arp_eth_source[1], packet->arp_eth_source[2], 00323 packet->arp_eth_source[3], packet->arp_eth_source[4], packet->arp_eth_source[5] 00324 ); 00325 #endif 00326 break; 00327 00328 default: 00329 kprintf("\n\rarp: message unknown!"); 00330 break; 00331 } 00332 } |
|
ARP cache mutex semaphore.
|
|
ARP cache (here are stored all addresses resolutions IP<->MAC).
|
|
Initial value: { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }
|
|
IP address.
|
|
Ethernet address.
|
|
Timestamp.
|