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 ){ |