Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4730 → Rev 4731

/branches/network/uspace/srv/net/il/ip/ip_header.h
67,10 → 67,20
#define IP_HEADER_CHECKSUM( header ) ( htons( ip_checksum(( uint8_t * )( header ), IP_HEADER_LENGTH( header ))))
 
/** Returns the fragment offest.
* @param header The IP packet header. Input parameter.
*/
#define IP_FRAGMENT_OFFSET( header ) (((( header )->fragment_offset_high << 8 ) + ( header )->fragment_offset_low ) * 8u )
 
/** Returns the fragment offest high bits.
* @param length The prefixed data total length. Input parameter.
*/
#define IP_COMPUTE_FRAGMENT_OFFSET( length ) (( length ) / 8 )
#define IP_COMPUTE_FRAGMENT_OFFSET_HIGH( length ) (((( length ) / 8u ) & 0x1F00 ) >> 8 )
 
/** Returns the fragment offest low bits.
* @param length The prefixed data total length. Input parameter.
*/
#define IP_COMPUTE_FRAGMENT_OFFSET_LOW( length ) ((( length ) / 8u ) & 0xFF )
 
/** Type definition of the internet header.
* @see ip_header
*/
117,20 → 127,25
uint16_t identification;
#ifdef ARCH_IS_BIG_ENDIAN
/** Various control flags.
* @see
*/
uint16_t flags:3;
uint8_t flags:3;
/** This field indicates where in the datagram this fragment belongs.
* High bits.
*/
uint16_t fragment_offset:3;
uint8_t fragment_offset_high:5;
#else
/** This field indicates where in the datagram this fragment belongs.
* High bits.
*/
uint16_t fragment_offset:13;
uint8_t fragment_offset_high:5;
/** Various control flags.
*/
uint16_t flags:3;
uint8_t flags:3;
#endif
/** This field indicates where in the datagram this fragment belongs.
* Low bits.
*/
uint8_t fragment_offset_low;
/** This field indicates the maximum time the datagram is allowed to remain in the internet system.
* If this field contains the value zero, then the datagram must be destroyed.
* This field is modified in internet header processing.
/branches/network/uspace/srv/net/il/ip/ip.c
404,18 → 404,10
}
 
int ip_device_state_message( device_id_t device_id, device_state_t state ){
// ERROR_DECLARE;
 
/* measured_string_t address;
measured_string_ref translation;
char * data;
*/
/* packet_t packet;
in_addr_t destination;
*/
ip_netif_ref netif;
 
fibril_rwlock_write_lock( & ip_globals.netifs_lock );
// find the device
netif = ip_netifs_find( & ip_globals.netifs, device_id );
if( ! netif ){
fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
422,51 → 414,9
return ENOENT;
}
netif->state = state;
// TODO state
printf( "ip - device %d changed state to %d\n\n", device_id, state );
fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
// if( netif->arp ){
/* address.value = ( char * ) & ip_globals.gateway.gateway.s_addr;
address.length = CONVERT_SIZE( ip_globals.gateway.gateway.s_addr, char, 1 );
if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ))){
ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ));
}
printf( "\tgateway translated to\t= %X:%X:%X:%X:%X:%X\n", data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ] );
free( translation );
free( data );
address.value = ( char * ) & ip_globals.gateway.gateway.s_addr;
address.length = CONVERT_SIZE( ip_globals.gateway.gateway.s_addr, char, 1 );
if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ))){
sleep( 2 );
ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ));
}
printf( "\tgateway translated to\t= %X:%X:%X:%X:%X:%X\n", data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ] );
free( translation );
free( data );
*//* printf( "IP - testing to send packet:\n" );
ERROR_PROPAGATE( inet_pton( AF_INET, "90.182.101.18", ( uint8_t * ) & destination.s_addr ));
packet = packet_get_4( ip_globals.net_phone, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
if( ! packet ) return ENOMEM;
pq_release( ip_globals.net_phone, packet_get_id( packet ));
packet = packet_get_4( ip_globals.net_phone, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
if( ! packet ) return ENOMEM;
pq_release( ip_globals.net_phone, packet_get_id( packet ));
packet = packet_get_4( ip_globals.net_phone, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
if( ! packet ) return ENOMEM;
pq_release( ip_globals.net_phone, packet_get_id( packet ));
packet = packet_get_4( ip_globals.net_phone, 1500, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
if( ! packet ) return ENOMEM;
// try this long version
// if( ERROR_OCCURRED( packet_copy_data( packet, "Hi, this is IP, wery long version 1, wery long version 2, wery long version 3, wery long version 4, wery long version 5, wery long version 6, wery long version 7, wery long version 8, wery long version 9, wery long version 10, wery long version 11, wery long version 12, wery long version 13, wery long version 14, wery long version 15, wery long version 16, wery long version 17, wery long version 18, wery long version 19, wery long version 20, wery long version 21, wery long version 22, wery long version 23, wery long version 24, wery long version 25, wery long version 26, wery long version 27, wery long version 28, wery long version 29, wery long version 30Hi, this is IP, wery long version 1, wery long version 2, wery long version 3, wery long version 4, wery long version 5, wery long version 6, wery long version 7, wery long version 8, wery long version 9, wery long version 10, wery long version 11, wery long version 12, wery long version 13, wery long version 14, wery long version 15, wery long version 16, wery long version 17, wery long version 18, wery long version 19, wery long version 20, wery long version 21, wery long version 22, wery long version 23, wery long version 24, wery long version 25, wery long version 26, wery long version 27, wery long version 28, wery long version 29, wery long version 30", 1330 ))
if( ERROR_OCCURRED( packet_copy_data( packet, "Hi, this is IP", 14 ))
|| ERROR_OCCURRED( packet_set_addr( packet, NULL, ( uint8_t * ) & destination.s_addr, 4 ))
|| ERROR_OCCURRED( ip_client_prepare_packet( packet, 0, 0, 0, 0, 0 ))){
pq_release( ip_globals.net_phone, packet_get_id( packet ));
}
ERROR_CODE = ip_send_msg( 0, 0, packet, SERVICE_IP );
printf( "send returned %d\n", ERROR_CODE );
}
*/ return EOK;
return EOK;
}
 
int ip_connect_module( services_t service ){
661,7 → 611,8
ERROR_PROPAGATE( packet_set_addr( packet, NULL, NULL, 0 ));
}
header->version = IPV4;
header->fragment_offset = 0;
header->fragment_offset_high = 0;
header->fragment_offset_low = 0;
header->header_checksum = 0;
if( source ) header->source_address = source->s_addr;
header->destination_address = dest.s_addr;
669,7 → 620,7
++ ip_globals.packet_counter;
header->identification = htons( ip_globals.packet_counter );
fibril_rwlock_write_unlock( & ip_globals.lock );
length = packet_get_data_length( packet );
// 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;
681,7 → 632,8
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 = IP_COMPUTE_FRAGMENT_OFFSET( length );
middle_header->fragment_offset_high = IP_COMPUTE_FRAGMENT_OFFSET_HIGH( length );
middle_header->fragment_offset_low = IP_COMPUTE_FRAGMENT_OFFSET_LOW( length );
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 )));
693,7 → 645,8
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 = IP_COMPUTE_FRAGMENT_OFFSET( length );
middle_header->fragment_offset_high = IP_COMPUTE_FRAGMENT_OFFSET_HIGH( length );
middle_header->fragment_offset_low = IP_COMPUTE_FRAGMENT_OFFSET_LOW( length );
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 )));
949,7 → 902,7
// biggest multiple of 8 lower than content
// TODO even fragmentation?
length = length & ( ~ 0x7 );// ( content / 8 ) * 8
if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, last_header, (( IP_TOTAL_LENGTH( header ) - length ) % ( length - IP_HEADER_LENGTH( last_header ))), src, dest, addrlen ))){
if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, last_header, (( IP_HEADER_DATA_LENGTH( header ) - (( length - IP_HEADER_LENGTH( header )) & ( ~ 0x7 ))) % (( length - IP_HEADER_LENGTH( last_header )) & ( ~ 0x7 ))), src, dest, addrlen ))){
return ip_release_and_return( packet, ERROR_CODE );
}
// mark the first as fragmented
962,7 → 915,7
if( ! middle_header ){
return ip_release_and_return( packet, ENOMEM );
}
if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, middle_header, length - IP_HEADER_LENGTH( middle_header ), src, dest, addrlen ))){
if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, middle_header, ( length - IP_HEADER_LENGTH( middle_header )) & ( ~ 0x7 ), src, dest, addrlen ))){
return ip_release_and_return( packet, ERROR_CODE );
}
}
975,6 → 928,7
ERROR_DECLARE;
 
void * data;
size_t offset;
 
data = packet_suffix( new_packet, length );
if( ! data ) return ENOMEM;
982,7 → 936,10
ERROR_PROPAGATE( packet_trim( packet, 0, length ));
header->total_length = htons( IP_TOTAL_LENGTH( header ) - length );
new_header->total_length = htons( IP_HEADER_LENGTH( new_header ) + length );
new_header->fragment_offset = header->fragment_offset + IP_HEADER_DATA_LENGTH( header ) / 8;
offset = IP_FRAGMENT_OFFSET( header ) + IP_HEADER_DATA_LENGTH( header );
printf( "offset %d = %d + %d\n", offset, IP_FRAGMENT_OFFSET( header ), IP_HEADER_DATA_LENGTH( header ));
new_header->fragment_offset_high = IP_COMPUTE_FRAGMENT_OFFSET_HIGH( offset );
new_header->fragment_offset_low = IP_COMPUTE_FRAGMENT_OFFSET_LOW( offset );
new_header->header_checksum = IP_HEADER_CHECKSUM( new_header );
ERROR_PROPAGATE( packet_set_addr( new_packet, ( const uint8_t * ) src, ( const uint8_t * ) dest, addrlen ));
return pq_insert_after( packet, new_packet );
1062,8 → 1019,12
}
// checksum
if(( header->header_checksum ) && ( IP_HEADER_CHECKSUM( header ))){
// TODO checksum error ICMP?
return ip_release_and_return( packet, EINVAL );
phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
if( phone >= 0 ){
// checksum error ICMP
icmp_parameter_problem_msg( phone, ICMP_PARAM_POINTER, (( size_t ) (( void * ) & header->header_checksum )) - (( size_t ) (( void * ) header )), packet );
}
return EINVAL;
}
if( header->ttl <= 1 ){
phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
1179,7 → 1140,7
// struct sockaddr_in dest_in6;
socklen_t addrlen;
 
if(( header->flags & IPFLAG_MORE_FRAGMENTS ) || header->fragment_offset ){
if(( header->flags & IPFLAG_MORE_FRAGMENTS ) || IP_FRAGMENT_OFFSET( header )){
// TODO fragmented
return ENOTSUP;
}else{
1259,7 → 1220,7
if( ! header ) return EINVAL;
}
// only for the first fragment
if( header->fragment_offset ) return EINVAL;
if( IP_FRAGMENT_OFFSET( header )) return EINVAL;
// set the destination address
switch( header->version ){
case IPVERSION: