00001
00002
00003
00004
00005
00006
00007
00008 #include <const.h>
00009 #include <errno.h>
00010
00011 #include <arch/mem.h>
00012
00013 #include <kernel/clock.h>
00014 #include <kernel/console.h>
00015 #include <kernel/kmalloc.h>
00016 #include <kernel/semaphore.h>
00017 #include <kernel/task.h>
00018
00019 #include <net/eth.h>
00020 #include <net/ip.h>
00021 #include <net/network.h>
00022 #include <net/rtl8139.h>
00023
00024 #include <net/arp.h>
00025
00026
00027 static uint8_t eth_bcast[ETH_ADDR_LEN] =
00028 {
00029 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
00030 };
00031
00032
00033 #define ARP_TABLE_DIM 10
00034
00035
00036 static struct
00037 {
00038
00039 in_addr_t ip;
00040
00041 uint8_t mac[ETH_ADDR_LEN];
00042
00043 uint32_t tickstamp;
00044 } arp_table[ARP_TABLE_DIM];
00045
00046
00047 semaphore_t arp_mutex;
00048
00049
00050
00051
00052
00053 bool mac_addr_cmp(uint8_t *m1, uint8_t *m2)
00054 {
00055 if ( memcmp(m1, m2, ETH_ADDR_LEN)==0 )
00056 return(TRUE);
00057 else
00058 return(FALSE);
00059 }
00060
00061
00062
00063
00064 void arp_add_cache(in_addr_t ip, uint8_t *mac)
00065 {
00066 uint32_t age_max=0, pos_max=0, age, ticks;
00067 int i;
00068
00069 DOWN(&arp_mutex);
00070
00071
00072 for(i=0; i<ARP_TABLE_DIM; i++)
00073 {
00074 if ( arp_table[i].ip == ip )
00075 {
00076
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
00085 for(i=0; i<ARP_TABLE_DIM; i++)
00086 {
00087 if ( arp_table[i].ip == 0 )
00088 {
00089
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
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
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 }
00113
00114
00115
00116
00117 bool arp_remove_cache(in_addr_t ip)
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
00132 UP(&arp_mutex);
00133 return(FALSE);
00134 }
00135
00136
00137 void arp_reset_cache()
00138 {
00139 INIT_MUTEX(&arp_mutex);
00140 memset(arp_table, 0, sizeof(arp_table));
00141 }
00142
00143
00144
00145
00146
00147 bool arp_ip_to_eth(uint8_t *eth_addr, in_addr_t ip_addr)
00148 {
00149 int i;
00150 timeout_t time1, time2;
00151
00152 if ( get_eth_mac_addr()==NULL )
00153
00154 return(FALSE);
00155
00156
00157 if ( (ip_addr==INADDR_ANY) || (ip_addr==get_host_ip()) )
00158 {
00159
00160 memcpy(eth_addr, get_eth_mac_addr(), ETH_ADDR_LEN);
00161 return(TRUE);
00162 }
00163
00164
00165 if ( (ip_addr==get_host_bcast()) || (ip_addr==INADDR_BROADCAST) )
00166 {
00167
00168 memcpy(eth_addr, eth_bcast, ETH_ADDR_LEN);
00169 return(TRUE);
00170 }
00171
00172
00173
00174 DOWN(&arp_mutex);
00175 for(i=0; i<ARP_TABLE_DIM; i++)
00176 {
00177 if ( arp_table[i].ip == ip_addr)
00178 {
00179
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
00189 set_timeout(&time1, 4000);
00190 set_timeout(&time2, 0);
00191
00192 while(TRUE)
00193 {
00194
00195 DOWN(&arp_mutex);
00196 for(i=0; i<ARP_TABLE_DIM; i++)
00197 {
00198 if ( arp_table[i].ip == ip_addr)
00199 {
00200
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
00210 if ( is_timeout(&time1) )
00211 {
00212
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
00239 send_arp_packet(ip_addr, eth_bcast, ARP_OP_REQUEST);
00240
00241 set_timeout(&time2, 1000);
00242 }
00243 idle();
00244 }
00245 }
00246
00247
00248
00249 void to_arp_layer(arp_t *packet)
00250 {
00251 #ifdef DEBUG
00252
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
00283 arp_add_cache(packet->arp_ip_source, packet->arp_eth_source);
00284
00285
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
00303 if (packet->arp_ip_dest == get_host_ip())
00304 {
00305
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
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 }
00333
00334
00335
00336
00337
00338
00339
00340
00341 int send_arp_packet(in_addr_t ip_to, const uint8_t *eth_to, uint16_t arp_op)
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
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
00359 if ( (mac_addr = get_eth_mac_addr()) == NULL )
00360
00361 return(-ENXIO);
00362
00363 memcpy(packet->arp_eth_source, mac_addr, ETH_ADDR_LEN);
00364
00365 packet->arp_ip_source = get_host_ip();
00366
00367
00368 memcpy(packet->arp_eth_dest, eth_to, ETH_ADDR_LEN);
00369
00370 packet->arp_ip_dest = ip_to;
00371
00372
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
00380 kfree(packet);
00381
00382 if ( tot_len < 0 )
00383
00384 return(tot_len);
00385
00386
00387 return(0);
00388 }
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399 int recv_arp_packet(arp_t *buf, size_t len)
00400 {
00401 return( -ENOPROTOOPT );
00402 }
00403
00404
00405
00406
00407
00408
00409 void arp_request(char *ip_dot)
00410 {
00411 uint8_t eth[ETH_ADDR_LEN];
00412 in_addr_t ip;
00413 int i;
00414
00415
00416
00417 if ( !inet_aton(ip_dot, &ip) )
00418 {
00419
00420
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
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 }