35,9 → 35,9 |
* @see arp.h |
*/ |
|
#include <as.h> |
#include <async.h> |
#include <malloc.h> |
#include <rwlock.h> |
#include <stdio.h> |
#include <string.h> |
|
160,7 → 160,13 |
GENERIC_CHAR_MAP_IMPLEMENT( arp_addr, measured_string_t ) |
|
int arp_initialize( void ){ |
return arp_cache_initialize( & arp_globals.cache ); |
ERROR_DECLARE; |
|
rwlock_initialize( & arp_globals.lock ); |
rwlock_write_lock( & arp_globals.lock ); |
ERROR_PROPAGATE( arp_cache_initialize( & arp_globals.cache )); |
rwlock_write_unlock( & arp_globals.lock ); |
return EOK; |
} |
|
int arp_proto_create( arp_proto_ref * proto, services_t service, measured_string_ref address ){ |
187,10 → 193,14 |
ipcarg_t result; |
arp_proto_ref proto; |
|
rwlock_write_lock( & arp_globals.lock ); |
// an existing device? |
device = arp_cache_find( & arp_globals.cache, device_id ); |
if( device ){ |
if( device->service != service ) return EEXIST; |
if( device->service != service ){ |
rwlock_write_unlock( & arp_globals.lock ); |
return EEXIST; |
} |
proto = arp_protos_find( & device->protos, protocol ); |
if( proto ){ |
free( proto->addr ); |
198,8 → 208,12 |
proto->addr = address; |
proto->addr_data = address->value; |
}else{ |
ERROR_PROPAGATE( arp_proto_create( & proto, protocol, address )); |
if( ERROR_OCCURRED( arp_proto_create( & proto, protocol, address ))){ |
rwlock_write_unlock( & arp_globals.lock ); |
return ERROR_CODE; |
} |
if( ERROR_OCCURRED( arp_protos_add( & device->protos, proto->service, proto ))){ |
rwlock_write_unlock( & arp_globals.lock ); |
free( proto ); |
return ERROR_CODE; |
} |
208,14 → 222,19 |
}else{ |
// create a new device |
device = ( arp_device_ref ) malloc( sizeof( arp_device_t )); |
if( ! device ) return ENOMEM; |
if( ! device ){ |
rwlock_write_unlock( & arp_globals.lock ); |
return ENOMEM; |
} |
device->device_id = device_id; |
if( ERROR_OCCURRED( arp_protos_initialize( & device->protos )) |
|| ERROR_OCCURRED( arp_proto_create( & proto, protocol, address ))){ |
rwlock_write_unlock( & arp_globals.lock ); |
free( device ); |
return ERROR_CODE; |
} |
if( ERROR_OCCURRED( arp_protos_add( & device->protos, proto->service, proto ))){ |
rwlock_write_unlock( & arp_globals.lock ); |
arp_protos_destroy( & device->protos ); |
free( device ); |
return ERROR_CODE; |
225,6 → 244,7 |
device->phone = bind_service( device->service, device->device_id, SERVICE_ARP, 0, arp_receiver ); |
// get packet dimensions |
if( ERROR_OCCURRED( async_req_1_4( device->phone, NET_NIL_PACKET_SPACE, device_id, & device->addr_len, & device->prefix, & device->content, & device->suffix ))){ |
rwlock_write_unlock( & arp_globals.lock ); |
arp_protos_destroy( & device->protos ); |
free( device ); |
return ERROR_CODE; |
232,6 → 252,7 |
// get hardware address |
message = async_send_1( device->phone, NET_NIL_ADDR, device->device_id, & answer ); |
if( ERROR_OCCURRED( measured_strings_return( device->phone, & device->addr, & device->addr_data, 1 ))){ |
rwlock_write_unlock( & arp_globals.lock ); |
arp_protos_destroy( & device->protos ); |
free( device ); |
async_wait_for( message, NULL ); |
239,6 → 260,7 |
} |
async_wait_for( message, & result ); |
if( ERROR_OCCURRED( result )){ |
rwlock_write_unlock( & arp_globals.lock ); |
free( device->addr ); |
free( device->addr_data ); |
arp_protos_destroy( & device->protos ); |
248,6 → 270,7 |
// get broadcast address |
message = async_send_1( device->phone, NET_NIL_BROADCAST_ADDR, device->device_id, & answer ); |
if( ERROR_OCCURRED( measured_strings_return( device->phone, & device->broadcast_addr, & device->broadcast_data, 1 ))){ |
rwlock_write_unlock( & arp_globals.lock ); |
free( device->addr ); |
free( device->addr_data ); |
arp_protos_destroy( & device->protos ); |
259,6 → 282,7 |
// add to the cache |
if( ERROR_OCCURRED( result ) |
|| ERROR_OCCURRED( arp_cache_add( & arp_globals.cache, device->device_id, device ))){ |
rwlock_write_unlock( & arp_globals.lock ); |
free( device->addr ); |
free( device->addr_data ); |
free( device->broadcast_addr ); |
268,6 → 292,7 |
return ERROR_CODE; |
} |
} |
rwlock_write_unlock( & arp_globals.lock ); |
return EOK; |
} |
|
280,19 → 305,33 |
arp_header_ref header; |
|
if( ! target ) return NULL; |
rwlock_read_lock( & arp_globals.lock ); |
device = arp_cache_find( & arp_globals.cache, device_id ); |
if( ! device ) return NULL; |
if( ! device ){ |
rwlock_read_unlock( & arp_globals.lock ); |
return NULL; |
} |
proto = arp_protos_find( & device->protos, protocol ); |
if(( ! proto ) || ( proto->addr->length != target->length )) return NULL; |
if(( ! proto ) || ( proto->addr->length != target->length )){ |
rwlock_read_unlock( & arp_globals.lock ); |
return NULL; |
} |
addr = arp_addr_find( & proto->addresses, target->value, target->length ); |
if( addr ) return addr; |
if( addr ){ |
rwlock_read_unlock( & arp_globals.lock ); |
return addr; |
} |
// ARP packet content size = header + ( address + translation ) * 2 |
length = 8 + ( CONVERT_SIZE( char, uint8_t, proto->addr->length ) + CONVERT_SIZE( char, uint8_t, device->addr->length )) * 2; |
if( length > device->content ){ |
rwlock_read_unlock( & arp_globals.lock ); |
return NULL; |
} |
packet = packet_get_5( arp_globals.networking_phone, SERVICE_ARP, device->addr_len, device->prefix, length, device->suffix ); |
if( ! packet ) return NULL; |
packet = packet_get_4( arp_globals.networking_phone, device->addr_len, device->prefix, length, device->suffix ); |
if( ! packet ){ |
rwlock_read_unlock( & arp_globals.lock ); |
return NULL; |
} |
header = ( arp_header_ref ) packet_suffix( packet, length ); |
header->hardware = device->hardware; |
header->hardware_length = device->addr->length; |
309,6 → 348,7 |
memcpy((( uint8_t * ) header ) + length, target->value, target->length ); |
packet_set_addr( packet, ( uint8_t * ) device->addr->value, ( uint8_t * ) device->broadcast_addr->value, CONVERT_SIZE( char, uint8_t, device->addr->length )); |
async_msg_3( device->phone, NET_NETIF_SEND, device_id, SERVICE_ARP, packet_get_id( packet )); |
rwlock_read_unlock( & arp_globals.lock ); |
return NULL; |
} |
|
319,14 → 359,8 |
arp_header_ref header; |
arp_device_ref device; |
arp_proto_ref proto; |
// arp_addr_ref addr; |
measured_string_ref hw_source; |
/* measured_string_t proto_target; |
aid_t message; |
ipcarg_t result; |
int index; |
ipc_call_t answer; |
*/ uint8_t * src_hw; |
uint8_t * src_hw; |
uint8_t * src_proto; |
uint8_t * des_hw; |
uint8_t * des_proto; |
333,13 → 367,23 |
|
length = packet_get_data_length( packet ); |
if( length <= sizeof( arp_header_t )) return EINVAL; |
rwlock_read_lock( & arp_globals.lock ); |
device = arp_cache_find( & arp_globals.cache, device_id ); |
if( ! device ) return ENOENT; |
if( ! device ){ |
rwlock_read_unlock( & arp_globals.lock ); |
return ENOENT; |
} |
header = ( arp_header_ref ) packet_get_data( packet ); |
if( header->hardware != device->hardware ) return EINVAL; |
if( length < sizeof( arp_header_t ) + ( header->hardware_length + header->protocol_length ) * 2 ) return EINVAL; |
if(( header->hardware != device->hardware ) |
|| ( length < sizeof( arp_header_t ) + ( header->hardware_length + header->protocol_length ) * 2 )){ |
rwlock_read_unlock( & arp_globals.lock ); |
return EINVAL; |
} |
proto = arp_protos_find( & device->protos, protocol_unmap( device->service, header->protocol )); |
if( ! proto ) return ENOENT; |
if( ! proto ){ |
rwlock_read_unlock( & arp_globals.lock ); |
return ENOENT; |
} |
src_hw = (( uint8_t * ) header ) + sizeof( arp_header_t ); |
src_proto = src_hw + header->hardware_length; |
des_hw = src_proto + header->protocol_length; |
347,48 → 391,41 |
hw_source = arp_addr_find( & proto->addresses, ( char * ) src_proto, CONVERT_SIZE( uint8_t, char, header->protocol_length )); |
// exists? |
if( hw_source ){ |
if( hw_source->length != CONVERT_SIZE( uint8_t, char, header->hardware_length )) return EINVAL; |
if( hw_source->length != CONVERT_SIZE( uint8_t, char, header->hardware_length )){ |
rwlock_read_unlock( & arp_globals.lock ); |
return EINVAL; |
} |
memcpy( hw_source->value, src_hw, hw_source->length ); |
} |
// is my protocol address? |
// TODO query protocol module? |
/* proto_target.value = des_proto; |
proto_target.length = header->protocol_length; |
// TODO send necessary? |
message = async_send_0( proto->phone, NET_IL_MY_ADDR, & answer ); |
if( ERROR_OCCURRED( measured_strings_send( device->phone, & proto_target, 1 ))){ |
async_wait_for( message, NULL ); |
return ERROR_CODE; |
if( proto->addr->length != CONVERT_SIZE( uint8_t, char, header->hardware_length )){ |
rwlock_read_unlock( & arp_globals.lock ); |
return EINVAL; |
} |
async_wait_for( message, & result ); |
if( result == EOK ){ |
*/ if( proto->addr->length != CONVERT_SIZE( uint8_t, char, header->hardware_length )) return EINVAL; |
if( ! strncmp( proto->addr->value, ( char * ) des_proto, proto->addr->length )){ |
// not already upadted? |
if( ! hw_source ){ |
hw_source = measured_string_create_bulk(( char * ) src_hw, CONVERT_SIZE( uint8_t, char, header->hardware_length )); |
if( ! hw_source ) return ENOMEM; |
ERROR_PROPAGATE( arp_addr_add( & proto->addresses, ( char * ) src_proto, CONVERT_SIZE( uint8_t, char, header->protocol_length ), hw_source )); |
if( ! hw_source ){ |
rwlock_read_unlock( & arp_globals.lock ); |
return ENOMEM; |
} |
if( ERROR_OCCURRED( arp_addr_add( & proto->addresses, ( char * ) src_proto, CONVERT_SIZE( uint8_t, char, header->protocol_length ), hw_source ))){ |
rwlock_read_unlock( & arp_globals.lock ); |
return ERROR_CODE; |
} |
} |
if( header->operation == ARPOP_REQUEST ){ |
header->operation = ARPOP_REPLY; |
/* for( index = 0; index + header->hardware_length < header->protocol_length; index += header->hardware_length ){ |
memcpy( src_hw, src_proto + index, header->hardware_length ); |
memcpy( src_proto + index, des_proto + index, header->hardware_length ); |
memcpy( des_proto + index, src_hw, header->hardware_length ); |
} |
memcpy( src_hw, src_proto + index, header->hardware_length - header->protocol_length ); |
memcpy( src_proto + index, des_proto + index, header->hardware_length - header->protocol_length ); |
memcpy( des_proto + index, src_hw, header->hardware_length - header->protocol_length ); |
memcpy( src_hw, des_hw, header->hardware_length ); |
memcpy( des_hw, hw_source->value, hw_source->length ); |
*/ memcpy( des_proto, src_proto, header->protocol_length ); |
memcpy( des_proto, src_proto, header->protocol_length ); |
memcpy( src_proto, proto->addr->value, header->protocol_length ); |
memcpy( src_hw, des_hw, header->hardware_length ); |
memcpy( des_hw, hw_source->value, header->hardware_length ); |
packet_set_addr( packet, src_hw, des_hw, header->hardware_length ); |
async_msg_3( device->phone, NET_NETIF_SEND, device_id, SERVICE_ARP, packet_get_id( packet )); |
rwlock_read_unlock( & arp_globals.lock ); |
}else{ |
rwlock_read_unlock( & arp_globals.lock ); |
packet_release( arp_globals.networking_phone, packet_get_id( packet )); |
} |
} |
398,9 → 435,14 |
int arp_clear_device_message( device_id_t device_id ){ |
arp_device_ref device; |
|
rwlock_write_lock( & arp_globals.lock ); |
device = arp_cache_find( & arp_globals.cache, device_id ); |
if( ! device ) return ENOENT; |
if( ! device ){ |
rwlock_write_unlock( & arp_globals.lock ); |
return ENOENT; |
} |
clear_device( device ); |
rwlock_write_unlock( & arp_globals.lock ); |
return EOK; |
} |
|
423,6 → 465,7 |
int count; |
arp_device_ref device; |
|
rwlock_write_lock( & arp_globals.lock ); |
count = arp_cache_count( & arp_globals.cache ); |
while( count > 0 ){ |
device = arp_cache_get_index( & arp_globals.cache, count ); |
433,6 → 476,7 |
} |
} |
arp_cache_clear( & arp_globals.cache ); |
rwlock_write_lock( & arp_globals.lock ); |
return EOK; |
} |
|
477,7 → 521,8 |
while( true ){ |
switch( IPC_GET_METHOD( * icall )){ |
case NET_IL_DEVICE_STATE: |
//TODO clear device if off? |
// do nothing - keep the cache |
ipc_answer_0( iid, EOK ); |
break; |
case NET_IL_RECEIVED: |
if( ! ERROR_OCCURRED( packet_translate( arp_globals.networking_phone, & packet, IPC_GET_PACKET( icall )))){ |