#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.
|
1.2.18