Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4588 → Rev 4589

/branches/network/uspace/srv/net/il/ip/ip_client.c
67,5 → 67,22
return EOK;
}
 
int ip_client_process_packet( packet_t packet, ip_protocol_t * protocol, ip_ttl_t * ttl, ip_tos_t * tos, int * dont_fragment, size_t * ipopt_length ){
ip_header_ref header;
 
header = ( ip_header_ref ) packet_get_data( packet );
if( ! header ) return ENOMEM;
if( protocol ) * protocol = header->protocol;
if( ttl ) * ttl = header->ttl;
if( tos ) * tos = header->tos;
if( dont_fragment ) * dont_fragment = header->flags & IPFLAG_DONT_FRAGMENT;
if( ipopt_length ){
* ipopt_length = header->ihl * 4 - sizeof( ip_header_t );
return packet_trim( packet, sizeof( ip_header_t ), 0 );
}else{
return packet_trim( packet, header->ihl * 4, 0 );
}
}
 
/** @}
*/
/branches/network/uspace/srv/net/il/ip/ip.c
110,7 → 110,7
int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, size_t addr_len );
int ip_fragment_packet_data( packet_t packet, packet_t new_packet, ip_header_ref header, ip_header_ref new_header, size_t length, void * src, void * dest, size_t address_length );
ip_header_ref ip_create_middle_header( packet_t packet, ip_header_ref last );
ip_header_ref ip_create_last_header( packet_t packet, ip_header_ref first );
void ip_create_last_header( ip_header_ref last, ip_header_ref first );
 
in_addr_t * ip_netif_addr( ip_netif_ref netif );
ip_route_ref ip_find_route( in_addr_t destination );
485,8 → 485,6
int ip_send_route( packet_t packet, ip_netif_ref netif, ip_route_ref route, in_addr_t * src, in_addr_t dest ){
ERROR_DECLARE;
 
packet_t next;
packet_t tmp;
measured_string_t destination;
measured_string_ref translation;
char * data;
508,31 → 506,19
return EINVAL;
}
}else translation = NULL;
// process packet queue
next = packet;
do{
if( ERROR_OCCURRED( ip_prepare_packet( src, dest, next, translation ))){
// release invalid packet
tmp = pq_detach( next );
if( next == packet ) packet = tmp;
pq_release( ip_globals.net_phone, packet_get_id( next ));
next = tmp;
}else{
next = pq_next( next );
if( ERROR_OCCURRED( ip_prepare_packet( src, dest, packet, translation ))){
pq_release( ip_globals.net_phone, packet_get_id( packet ));
}else{
packet = ip_split_packet( packet, netif->prefix, netif->content, netif->suffix, netif->addr_len );
if( packet ){
nil_send_msg( netif->phone, netif->device_id, packet, SERVICE_IP );
}
}while( next );
}
if( translation ){
free( translation );
free( data );
}
// send packet queue
if( packet ){
packet = ip_split_packet( packet, netif->prefix, netif->content, netif->suffix, netif->addr_len );
if( packet ){
nil_send_msg( netif->phone, netif->device_id, packet, SERVICE_IP );
}
}
return EOK;
return ERROR_CODE;
}
 
int ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination ){
540,6 → 526,9
 
size_t length;
ip_header_ref header;
ip_header_ref last_header;
ip_header_ref middle_header;
packet_t next;
 
length = packet_get_data_length( packet );
if(( length < sizeof( ip_header_t )) || ( length > IP_MAX_CONTENT )) return EINVAL;
548,8 → 537,8
ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
}
header->version = 4;
header->total_length = htons( length );
header->fragment_offset = 0;
header->header_checksum = 0;
if( source ) header->source_address = source->s_addr;
header->destination_address = dest.s_addr;
fibril_rwlock_write_lock( & ip_globals.lock );
556,12 → 545,47
++ ip_globals.packet_counter;
header->identification = htons( ip_globals.packet_counter );
fibril_rwlock_write_unlock( & ip_globals.lock );
header->header_checksum = 0;
length = packet_get_data_length( packet );
if( pq_next( packet )){
last_header = ( ip_header_ref ) malloc( IP_HEADER_LENGTH( header ));
if( ! last_header ) return ENOMEM;
ip_create_last_header( last_header, header );
next = pq_next( packet );
while( pq_next( next )){
middle_header = ( ip_header_ref ) packet_prefix( next, IP_HEADER_LENGTH( last_header ));
if( ! middle_header ) return ENOMEM;
memcpy( middle_header, last_header, IP_HEADER_LENGTH( last_header ));
header->flags |= IPFLAG_MORE_FRAGMENTS;
middle_header->total_length = htons( packet_get_data_length( next ));
middle_header->fragment_offset = length / 8;
middle_header->header_checksum = IP_HEADER_CHECKSUM( middle_header );
if( destination ){
ERROR_PROPAGATE( packet_set_addr( next, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
}
length += packet_get_data_length( next );
next = pq_next( next );
}
middle_header = ( ip_header_ref ) packet_prefix( next, IP_HEADER_LENGTH( last_header ));
if( ! middle_header ) return ENOMEM;
memcpy( middle_header, last_header, IP_HEADER_LENGTH( last_header ));
middle_header->total_length = htons( packet_get_data_length( next ));
middle_header->fragment_offset = length / 8;
middle_header->header_checksum = IP_HEADER_CHECKSUM( middle_header );
if( destination ){
ERROR_PROPAGATE( packet_set_addr( next, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
}
length += packet_get_data_length( next );
free( last_header );
header->flags |= IPFLAG_MORE_FRAGMENTS;
}
header->total_length = htons( length );
// unnecessary for all protocols
header->header_checksum = IP_HEADER_CHECKSUM( header );
return EOK;
}
 
 
 
int ip_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
ERROR_DECLARE;
 
760,11 → 784,18
// create the last fragment
new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, ((( size_t ) address_length > addr_len ) ? ( size_t ) address_length : addr_len ));
if( ! new_packet ) return ENOMEM;
last_header = ip_create_last_header( new_packet, header );
// allocate as much as originally
last_header = ( ip_header_ref ) packet_suffix( new_packet, IP_HEADER_LENGTH( header ));
if( ! last_header ){
pq_release( ip_globals.net_phone, packet_get_id( new_packet ));
return ENOMEM;
}
ip_create_last_header( last_header, header );
// trim the unused space
if( ERROR_OCCURRED( packet_trim( new_packet, 0, IP_HEADER_LENGTH( header ) - IP_HEADER_LENGTH( last_header )))){
pq_release( ip_globals.net_phone, packet_get_id( new_packet ));
return ERROR_CODE;
}
// biggest multiple of 8 lower than content
// TODO even fragmentation?
length = length & ( ~ 0x7 );// ( content / 8 ) * 8
821,15 → 852,11
return middle;
}
 
ip_header_ref ip_create_last_header( packet_t packet, ip_header_ref first ){
ip_header_ref last;
void ip_create_last_header( ip_header_ref last, ip_header_ref first ){
ip_option_ref option;
size_t next;
size_t length;
 
// allocate as much as originally
last = ( ip_header_ref ) packet_suffix( packet, IP_HEADER_LENGTH( first ));
if( ! last ) return NULL;
// copy first itself
memcpy( last, first, sizeof( ip_header_t ));
length = sizeof( ip_header_t );
857,9 → 884,7
}else{
last->ihl = length / 4;
}
// trim the unused space
if( packet_trim( packet, 0, IP_HEADER_LENGTH( first ) - IP_HEADER_LENGTH( last )) != EOK ) return NULL;
return last;
last->header_checksum = 0;
}
 
int ip_received_msg( device_id_t device_id, packet_t packet ){