Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4730 → Rev 4731

/branches/network/uspace/srv/net/tl/icmp/icmp.c
228,10 → 228,18
* Sets the message type and code and computes the checksum.
* Error messages are sent only if allowed in the configuration.
* Releases the packet on errors.
* @param type The message type. Input parameter.
* @param code The message code. Input parameter.
* @param packet The message packet to be sent. Input parameter.
* @param header The ICMP header. Input parameter.
* @param error The error service to be announced. Should be SERVICE_ICMP or zero (0). Input parametr.
* @param ttl The time to live. Input parameter.
* @param tos The type of service. Input parameter.
* @param dont_fragment The value indicating whether the datagram must not be fragmented. Is used as a MTU discovery. Input parameter.
* @returns EOK on success.
* @returns EPERM if the error message is not allowed.
*/
int icmp_send_packet( icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error );
int icmp_send_packet( icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment );
 
/** Tries to set the pending reply result as the received message type.
* If the reply data are still present, the reply timeouted and the parent fibril is awaken.
404,7 → 412,7
fibril_rwlock_write_unlock( & icmp_globals.lock );
 
// send the request
icmp_send_packet( ICMP_ECHO, 0, packet, header, 0 );
icmp_send_packet( ICMP_ECHO, 0, packet, header, 0, ttl, tos, dont_fragment );
 
// wait for a reply
fibril_condvar_wait( & reply->condvar, & reply->mutex );
428,7 → 436,7
if( mtu ){
header->un.frag.mtu = mtu;
}
return icmp_send_packet( ICMP_DEST_UNREACH, code, packet, header, SERVICE_ICMP );
return icmp_send_packet( ICMP_DEST_UNREACH, code, packet, header, SERVICE_ICMP, 0, 0, 0 );
}
 
int icmp_source_quench_msg( int icmp_phone, packet_t packet ){
438,7 → 446,7
if( ! header ){
return icmp_release_and_return( packet, ENOMEM );
}
return icmp_send_packet( ICMP_SOURCE_QUENCH, 0, packet, header, SERVICE_ICMP );
return icmp_send_packet( ICMP_SOURCE_QUENCH, 0, packet, header, SERVICE_ICMP, 0, 0, 0 );
}
 
int icmp_time_exceeded_msg( int icmp_phone, icmp_code_t code, packet_t packet ){
448,7 → 456,7
if( ! header ){
return icmp_release_and_return( packet, ENOMEM );
}
return icmp_send_packet( ICMP_TIME_EXCEEDED, code, packet, header, SERVICE_ICMP );
return icmp_send_packet( ICMP_TIME_EXCEEDED, code, packet, header, SERVICE_ICMP, 0, 0, 0 );
}
 
int icmp_parameter_problem_msg( int icmp_phone, icmp_code_t code, icmp_param_t pointer, packet_t packet ){
459,7 → 467,7
return icmp_release_and_return( packet, ENOMEM );
}
header->un.param.pointer = pointer;
return icmp_send_packet( ICMP_PARAMETERPROB, code, packet, header, SERVICE_ICMP );
return icmp_send_packet( ICMP_PARAMETERPROB, code, packet, header, SERVICE_ICMP, 0, 0, 0 );
}
 
icmp_header_ref icmp_prepare_packet( packet_t packet ){
482,7 → 490,7
return header;
}
 
int icmp_send_packet( icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error ){
int icmp_send_packet( icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment ){
ERROR_DECLARE;
 
// do not send an error if disabled
493,7 → 501,7
header->code = code;
header->checksum = 0;
header->checksum = ICMP_CHECKSUM( header, packet_get_data_length( packet ));
if( ERROR_OCCURRED( ip_client_prepare_packet( packet, IPPROTO_ICMP, 0, 0, 0, 0 ))){
if( ERROR_OCCURRED( ip_client_prepare_packet( packet, IPPROTO_ICMP, ttl, tos, dont_fragment, 0 ))){
return icmp_release_and_return( packet, ERROR_CODE );
}
return ip_send_msg( icmp_globals.ip_phone, -1, packet, SERVICE_ICMP, error );
587,8 → 595,6
result = icmp_client_process_packet( packet, & type, & code, NULL, NULL );
if( result < 0 ) return result;
length = ( size_t ) result;
// TODO remove debug dump
printf( "ICMP error %d (%d) in packet %d\n", type, code, packet_get_id( packet ) );
// remove the error header
ERROR_PROPAGATE( packet_trim( packet, length, 0 ));
break;
639,7 → 645,7
// set both addresses to the source one (avoids the source address deletion before setting the destination one)
&& ( packet_set_addr( packet, src, src, ( size_t ) addrlen ) == EOK )){
// send the reply
icmp_send_packet( ICMP_ECHOREPLY, 0, packet, header, 0 );
icmp_send_packet( ICMP_ECHOREPLY, 0, packet, header, 0, 0, 0, 0 );
return EOK;
}else{
return EINVAL;
/branches/network/uspace/srv/net/tl/tl_common.c
99,7 → 99,7
}
}
 
void tl_send_icmp_port_unreachable( int packet_phone, int icmp_phone, packet_t packet, services_t error ){
int tl_prepare_icmp_packet( int packet_phone, int icmp_phone, packet_t packet, services_t error ){
packet_t next;
uint8_t * src;
int length;
115,10 → 115,11
&& ( icmp_phone >= 0 )
// set both addresses to the source one (avoids the source address deletion before setting the destination one)
&& ( packet_set_addr( packet, src, src, ( size_t ) length ) == EOK )){
icmp_destination_unreachable_msg( icmp_phone, ICMP_PORT_UNREACH, 0, packet );
return EOK;
}else{
pq_release( packet_phone, packet_get_id( packet ));
}
return ENOENT;
}
 
int tl_socket_read_packet_data( int packet_phone, packet_ref packet, size_t prefix, const packet_dimension_ref dimension, const struct sockaddr * addr, socklen_t addrlen ){
/branches/network/uspace/srv/net/tl/udp/udp.c
243,7 → 243,6
size_t length;
size_t offset;
int result;
uint8_t * data;
udp_header_ref header;
socket_core_ref * socket;
packet_t next_packet;
260,14 → 259,13
if( error ){
switch( error ){
case SERVICE_ICMP:
// ignore error
// length = icmp_client_header_length( packet );
// process error
// TODO remove debug dump
// length = icmp_client_header_length( packet );
result = icmp_client_process_packet( packet, & type, & code, NULL, NULL );
if( result < 0 ){
return udp_release_and_return( packet, result );
}
printf( "ICMP error %d (%d) in packet %d\n", type, code, packet_get_id( packet ) );
length = ( size_t ) result;
if( ERROR_OCCURRED( packet_trim( packet, length, 0 ))){
return udp_release_and_return( packet, ERROR_CODE );
291,22 → 289,26
if( length < sizeof( udp_header_t ) + offset ){
return udp_release_and_return( packet, NO_DATA );
}
data = packet_get_data( packet );
if( ! data ){
 
// trim all but UDP header
if( ERROR_OCCURRED( packet_trim( packet, offset, 0 ))){
return udp_release_and_return( packet, ERROR_CODE );
}
 
// get udp header
header = ( udp_header_ref ) packet_get_data( packet );
if( ! header ){
return udp_release_and_return( packet, NO_DATA );
}
// get udp header
header = ( udp_header_ref )( data + offset );
// find the destination socket
socket = socket_ports_find( & udp_globals.sockets, ntohs( header->destination_port ));
if( ! socket ){
tl_send_icmp_port_unreachable( udp_globals.net_phone, udp_globals.icmp_phone, packet, error );
if( tl_prepare_icmp_packet( udp_globals.net_phone, udp_globals.icmp_phone, packet, error ) == EOK ){
icmp_destination_unreachable_msg( udp_globals.icmp_phone, ICMP_PORT_UNREACH, 0, packet );
}
return EADDRNOTAVAIL;
}
 
// trim after successful processing to be able to send an ICMP error message!
ERROR_PROPAGATE( packet_trim( packet, offset, 0 ));
 
// count the received packet fragments
next_packet = packet;
fragments = 0;
363,10 → 365,11
// check checksum
if( header->checksum ){
if( flip_checksum( compact_checksum( checksum ))){
// TODO checksum error ICMP?
// TODO remove debug dump
printf("udp check failed %x => %x\n", header->checksum, flip_checksum( compact_checksum( checksum )));
return udp_release_and_return( packet, EINVAL );
if( tl_prepare_icmp_packet( udp_globals.net_phone, udp_globals.icmp_phone, packet, error ) == EOK ){
// checksum error ICMP
icmp_parameter_problem_msg( udp_globals.icmp_phone, ICMP_PARAM_POINTER, (( size_t ) (( void * ) & header->checksum )) - (( size_t ) (( void * ) header )), packet );
}
return EINVAL;
}
}
 
436,6 → 439,7
// fibril_rwlock_write_lock( & lock );
res = socket_create( & local_sockets, app_phone, NULL, SOCKET_SET_SOCKET_ID( answer ));
// fibril_rwlock_write_unlock( & lock );
// TODO max fragment size
* SOCKET_SET_DATA_FRAGMENT_SIZE( answer ) = MAX_UDP_FRAGMENT_SIZE;
* SOCKET_SET_HEADER_SIZE( answer ) = sizeof( udp_header_t );
answer_count = 3;
582,11 → 586,7
free( ip_header );
return udp_release_and_return( packet, ERROR_CODE );
}
/*// TODO remove debug dump:
uint8_t * data;
data = ip_header;
printf( "ip_header:\tlength\t= %d\n\tdata\t= %.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX\n", headerlen, data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ], data[ 6 ], data[ 7 ], data[ 8 ], data[ 9 ], data[ 10 ], data[ 11 ] );
*/ checksum = compute_checksum( checksum, ip_header, headerlen );
checksum = compute_checksum( checksum, ip_header, headerlen );
checksum = compute_checksum( checksum, ( uint8_t * ) header, sizeof( * header ));
header->checksum = htons( flip_checksum( compact_checksum( checksum )));
free( ip_header );
/branches/network/uspace/srv/net/tl/tl_common.h
91,15 → 91,17
*/
int tl_set_address_port( struct sockaddr * addr, int addrlen, uint16_t port );
 
/** Sends the port unreachable ICMP notification.
* Sends the first packet and releases all the others.
* Releases the packet queu on error.
/** Prepares the packet for ICMP error notification.
* Keeps the first packet and releases all the others.
* Releases all the packets on error.
* @param packet_phone The packet server module phone. Input parameter.
* @param icmp_phone The ICMP module phone. Input parameter.
* @param packet The packet to be send. Input parameter.
* @param error The packet error reporting service. Prefixes the received packet. Input parameter.
* @returns EOK on success.
* @returns ENOENT if no packet may be sent.
*/
void tl_send_icmp_port_unreachable( int packet_phone, int icmp_phone, packet_t packet, services_t error );
int tl_prepare_icmp_packet( int packet_phone, int icmp_phone, packet_t packet, services_t error );
 
/** Receives data from the socket into a packet.
* @param packet_phone The packet server module phone. Input parameter.
/branches/network/uspace/srv/net/app/ping/ping.c
149,7 → 149,7
printf( "Task %d - ", task_get_id());
printf( "%s\n", NAME );
 
for( index = 1; index < argc - 1; ++ index ){
for( index = 1; ( index < argc - 1 ) || (( index == argc ) && ( argv[ index ][ 0 ] == '-' )); ++ index ){
if( argv[ index ][ 0 ] == '-' ){
switch( argv[ index ][ 1 ] ){
case 'c': ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & count, "count", 0 ));
/branches/network/uspace/srv/net/app/echo/echo.c
221,6 → 221,7
fprintf( stderr, "Receive size too small (%d). Using 1024 bytes instead.\n", size );
size = 1024;
}
// size plus terminating null (\0)
data = ( char * ) malloc( size + 1 );
if( ! data ){
fprintf( stderr, "Failed to allocate receive buffer.\n" );
284,7 → 285,7
fprintf( stderr, "Received address error %d\n", ERROR_CODE );
}else{
data[ length ] = '\0';
printf( "Received from %s:%d\n%s\n", address_string, port, data );
printf( "Received %d bytes from %s:%d\n%s\n", length, address_string, port, data );
}
}
}
/branches/network/uspace/srv/net/nil/eth/eth.c
77,7 → 77,7
 
/** Maximum packet content length.
*/
#define ETH_MAX_CONTENT 1500
#define ETH_MAX_CONTENT 1500u
 
/** Minimum packet content length.
*/
273,7 → 273,6
int index;
eth_proto_ref proto;
 
//TODO clear device if off?
fibril_rwlock_read_lock( & eth_globals.protos_lock );
for( index = eth_protos_count( & eth_globals.protos ) - 1; index >= 0; -- index ){
proto = eth_protos_get_index( & eth_globals.protos, index );
/branches/network/uspace/srv/net/structures/packet/packet_header.h
39,6 → 39,21
 
#include "packet.h"
 
/** Returns the actual packet data length.
* @param header The packet header. Input parameter.
*/
#define PACKET_DATA_LENGTH( header ) (( header )->data_end - ( header )->data_start )
 
/** Returns the maximum packet address length.
* @param header The packet header. Input parameter.
*/
#define PACKET_MAX_ADDRESS_LENGTH( header ) (( header )->dest_addr - ( header )->src_addr )
 
/** Returns the minimum packet suffix.
* @param header The packet header. Input parameter.
*/
#define PACKET_MIN_SUFFIX( header ) (( header )->length - ( header )->data_start - ( header )->max_content )
 
/** Packet integrity check magic value.
*/
#define PACKET_MAGIC_VALUE 0x11227788
52,7 → 67,7
/** Packet queue sorting value.
* The packet queue is sorted the ascending order.
*/
int order;
size_t order;
/** Packet metric.
*/
size_t metric;
/branches/network/uspace/srv/net/structures/packet/packet_client.c
71,7 → 71,7
 
int packet_trim( packet_t packet, size_t prefix, size_t suffix ){
if( ! packet_is_valid( packet )) return EINVAL;
if( prefix + suffix > packet->data_end - packet->data_start ) return ENOMEM;
if( prefix + suffix > PACKET_DATA_LENGTH( packet )) return ENOMEM;
packet->data_start += prefix;
packet->data_end -= suffix;
return EOK;
91,7 → 91,7
 
size_t packet_get_data_length( const packet_t packet ){
if( ! packet_is_valid( packet )) return 0;
return packet->data_end - packet->data_start;
return PACKET_DATA_LENGTH( packet );
}
 
void * packet_get_data( const packet_t packet ){
104,7 → 104,7
size_t allocated;
 
if( ! packet_is_valid( packet )) return EINVAL;
allocated = packet->dest_addr - packet->src_addr;
allocated = PACKET_MAX_ADDRESS_LENGTH( packet );
if( allocated < addr_len ) return ENOMEM;
padding = allocated - addr_len;
packet->addr_len = addr_len;
123,5 → 123,30
return EOK;
}
 
packet_t packet_get_copy( int phone, packet_t packet ){
packet_t copy;
uint8_t * src;
uint8_t * dest;
size_t addrlen;
 
if( ! packet_is_valid( packet )) return NULL;
// get a new packet
copy = packet_get_4( phone, PACKET_DATA_LENGTH( packet ), PACKET_MAX_ADDRESS_LENGTH( packet ), packet->max_prefix, PACKET_MIN_SUFFIX( packet ));
if( ! copy ) return NULL;
// get addresses
addrlen = packet_get_addr( packet, & src, & dest );
// copy data
if(( packet_copy_data( copy, packet_get_data( packet ), PACKET_DATA_LENGTH( packet )) == EOK )
// copy addresses if present
&& (( addrlen <= 0 ) || ( packet_set_addr( copy, src, dest, addrlen ) == EOK ))){
copy->order = packet->order;
copy->metric = packet->metric;
return copy;
}else{
pq_release( phone, copy->packet_id );
return NULL;
}
}
 
/** @}
*/
/branches/network/uspace/srv/net/structures/packet/packet.c
183,11 → 183,11
// leave locked
}
 
packet_t pq_add( packet_t first, packet_t packet, int order, size_t metric ){
packet_t pq_add( packet_t first, packet_t packet, size_t order, size_t metric ){
packet_t item;
 
if( ! packet_is_valid( packet )) return NULL;
pq_set( packet, order, metric );
pq_set_order( packet, order, metric );
if( packet_is_valid( first )){
item = first;
do{
205,7 → 205,7
item->previous = packet->packet_id;
item = pm_find( packet->previous );
if( item ) item->next = packet->packet_id;
return item;
return item ? first : packet;
}
}while( packet_is_valid( item ));
}
212,6 → 212,21
return packet;
}
 
packet_t pq_find( packet_t packet, size_t order ){
packet_t item;
 
if( ! packet_is_valid( packet )) return NULL;
if( packet->order == order ) return packet;
item = pm_find( packet->next );
while( item && ( item != packet )){
item = pm_find( item->next );
if( item->order == order ){
return item;
}
}
return NULL;
}
 
int pq_insert_after( packet_t packet, packet_t new_packet ){
packet_t item;
 
242,7 → 257,7
return next;
}
 
int pq_set( packet_t packet, int order, size_t metric ){
int pq_set_order( packet_t packet, size_t order, size_t metric ){
if( ! packet_is_valid( packet )) return EINVAL;
packet->order = order;
packet->metric = metric;
249,6 → 264,13
return EOK;
}
 
int pq_get_order( packet_t packet, size_t * order, size_t * metric ){
if( ! packet_is_valid( packet )) return EINVAL;
if( order ) * order = packet->order;
if( metric ) * metric = packet->metric;
return EOK;
}
 
void pq_destroy( packet_t first, void ( * packet_release )( packet_t packet )){
packet_t actual;
packet_t next;
/branches/network/uspace/srv/net/structures/packet/packet_client.h
203,6 → 203,10
*/
void pq_release( int phone, packet_id_t packet_id );
 
/** \todo
*/
packet_t packet_get_copy( int phone, packet_t packet );
 
/*@}*/
 
#endif
/branches/network/uspace/srv/net/structures/packet/packet.h
109,11 → 109,20
* @returns The first packet of the queue. The original first packet may be shifted by the new packet.
* @returns NULL if the packet is not valid.
*/
packet_t pq_add( packet_t first, packet_t packet, int order, size_t metric );
packet_t pq_add( packet_t first, packet_t packet, size_t order, size_t metric );
 
/** Finds the packet with the given order.
* @param first The first packet of the queue. Input parameter.
* @param order The packet order value. Input parameter.
* @returns The packet with the given order.
* @returns NULL if the first packet is not valid.
* @returns NULL if the packet is not found.
*/
packet_t pq_find( packet_t first, size_t order );
 
/** Inserts packet after the given one.
* @param packet The packet in the queue. Input parameter.
* @param new_packet The new packet to be inserted.
* @param new_packet The new packet to be inserted. Input parameter.
* @returns EOK on success.
* @returns EINVAL if etiher of the packets is invalid.
*/
131,9 → 140,20
* @param packet The packet to be set. Input parameter.
* @param order The packet order value. Input parameter.
* @param metric The metric value of the packet. Input parameter.
* @returns EOK on success.
* @returns EINVAL if the packet is invalid..
*/
int pq_set( packet_t packet, int order, size_t metric );
int pq_set_order( packet_t packet, size_t order, size_t metric );
 
/** Sets the packet order and metric attributes.
* @param packet The packet to be set. Input parameter.
* @param order The packet order value. Output parameter.
* @param metric The metric value of the packet. Ouput parameter.
* @returns EOK on success.
* @returns EINVAL if the packet is invalid..
*/
int pq_get_order( packet_t packet, size_t * order, size_t * metric );
 
/** Releases the whole queue.
* Detaches all packets of the queue and calls the packet_release() for each of them.
* @param first The first packet of the queue. Input parameter.
/branches/network/uspace/srv/net/structures/packet/packet_server.c
35,10 → 35,10
*/
 
#include <align.h>
#include <assert.h>
#include <async.h>
#include <errno.h>
#include <fibril_sync.h>
//#include <stdio.h>
#include <unistd.h>
 
#include <ipc/ipc.h>
225,6 → 225,7
 
for( index = 0; ( index < FREE_QUEUES_COUNT - 1 ) && ( packet->length > ps_globals.sizes[ index ] ); ++ index );
ps_globals.free[ index ] = pq_add( ps_globals.free[ index ], packet, packet->length, packet->length );
assert( ps_globals.free[ index ] );
}
 
packet_t packet_get( size_t addr_len, size_t max_prefix, size_t max_content, size_t max_suffix ){
/branches/network/uspace/srv/net/include/tl_interface.h
58,7 → 58,7
/** Notifies the remote transport layer modules about the received packet/s.
* @param tl_phone The transport layer module phone used for remote calls. Input parameter.
* @param device_id The device identifier. Input parameter.
* @param packet The received packet or the received packet queue. Input parameter.
* @param packet The received packet or the received packet queue. The packet queue is used to carry a~fragmented datagram. The first packet contains the headers, the others contain only data. Input parameter.
* @param target The target transport layer module service to be delivered to. Input parameter.
* @param error The packet error reporting service. Prefixes the received packet. Input parameter.
* @returns EOK on success.
/branches/network/uspace/srv/net/include/ip_interface.h
100,9 → 100,10
int ip_device_req( int ip_phone, device_id_t device_id, services_t netif );
 
/** Sends the packet queue.
* The packets may get fragmented if needed.
* @param ip_phone The IP module phone used for (semi)remote calls. Input parameter.
* @param device_id The device identifier. Input parameter.
* @param packet The packet queue. Input parameter.
* @param packet The packet fragments as a~packet queue. All the packets have to have the same destination address. Input parameter.
* @param sender The sending module service. Input parameter.
* @param error The packet error reporting service. Prefixes the received packet. Input parameter.
* @returns EOK on success.
/branches/network/uspace/srv/net/modules.c
139,10 → 139,13
size_t length;
ipc_callid_t callid;
 
if(( ! ipc_data_read_receive( & callid, & length ))
|| ( length < data_length )){
if( ! ipc_data_read_receive( & callid, & length )){
return EINVAL;
}
if( length < data_length ){
ipc_data_read_finalize( callid, data, length );
return EOVERFLOW;
}
return ipc_data_read_finalize( callid, data, data_length );
}
 
/branches/network/uspace/srv/net/modules.h
109,7 → 109,8
* @param data The data buffer to be sent. Input parameter.
* @param data_length The buffer length. Input parameter.
* @returns EOK on success.
* @returns EINVAL if the client does not expect all the data.
* @returns EINVAL if the client does not expect the data.
* @returns EOVERFLOW if the client does not expect all the data. Only partial data are transfered.
* @returns Other error codes as defined for the ipc_data_read_finalize() function.
*/
int data_reply( void * data, size_t data_length );
/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:
/branches/network/uspace/srv/net/netif/netif_module.h
66,6 → 66,7
* @param packet The packet queue. Input parameter.
* @param sender The sending module service. Input parameter.
* @returns EOK on success.
* @returns EFORWARD if the device is not active (in the NETIF_ACTIVE state).
* @returns Other error codes as defined for the find_device() function.
* @returns Other error codes as defined for the specific module message implementation.
*/
/branches/network/uspace/srv/net/netif/dp8390/dp8390_module.c
221,6 → 221,10
packet_t next;
 
ERROR_PROPAGATE( find_device( device_id, & device ));
if( device->state != NETIF_ACTIVE ){
netif_pq_release( packet_get_id( packet ));
return EFORWARD;
}
dep = ( dpeth_t * ) device->specific;
// process packet queue
do{
/branches/network/uspace/srv/net/netif/lo/lo.c
185,7 → 185,10
int phone;
 
ERROR_PROPAGATE( find_device( device_id, & device ));
if( device->state != NETIF_ACTIVE ) return EPERM;
if( device->state != NETIF_ACTIVE ){
netif_pq_release( packet_get_id( packet ));
return EFORWARD;
}
next = packet;
do{
++ (( device_stats_ref ) device->specific )->send_packets;