Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4721 → Rev 4722

/branches/network/uspace/srv/net/tl/icmp/icmp.c
75,6 → 75,14
#include "icmp_messages.h"
#include "icmp_module.h"
 
/** Default ICMP error reporting.
*/
#define NET_DEFAULT_ICMP_ERROR_REPORTING true
 
/** Default ICMP echo replying.
*/
#define NET_DEFAULT_ICMP_ECHO_REPLYING true
 
/** Original datagram length in bytes transfered to the error notification message.
*/
#define ICMP_KEEP_LENGTH 8
500,12 → 508,14
index = icmp_bind_free_id( echo_data );
if( index < 0 ){
free( echo_data );
fibril_rwlock_write_unlock( & icmp_globals.lock );
return index;
}else{
id = echo_data->id;
fibril_rwlock_write_unlock( & icmp_globals.lock );
// return the echo data identifier as the ICMP phone
return id;
}
fibril_rwlock_write_unlock( & icmp_globals.lock );
// return the echo data identifier as the ICMP phone
return id;
}
 
int icmp_initialize( async_client_conn_t client_connection ){
527,12 → 537,18
ERROR_PROPAGATE( ip_packet_size_req( icmp_globals.ip_phone, -1, & icmp_globals.addr_len, & icmp_globals.prefix, & icmp_globals.content, & icmp_globals.suffix ));
icmp_globals.prefix += sizeof( icmp_header_t );
icmp_globals.content -= sizeof( icmp_header_t );
// get configuration
icmp_globals.error_reporting = NET_DEFAULT_ICMP_ERROR_REPORTING;
icmp_globals.echo_replying = NET_DEFAULT_ICMP_ECHO_REPLYING;
configuration = & names[ 0 ];
// get configuration
ERROR_PROPAGATE( net_get_conf_req( icmp_globals.net_phone, & configuration, count, & data ));
if( configuration ){
icmp_globals.error_reporting = configuration[ 0 ].value && ( configuration[ 0 ].value[ 0 ] == 'y' );
icmp_globals.echo_replying = configuration[ 1 ].value && ( configuration[ 1 ].value[ 0 ] == 'y' );
if( configuration[ 0 ].value ){
icmp_globals.error_reporting = ( configuration[ 0 ].value[ 0 ] == 'y' );
}
if( configuration[ 1 ].value ){
icmp_globals.echo_replying = ( configuration[ 1 ].value[ 0 ] == 'y' );
}
net_free_settings( configuration, data );
}
fibril_rwlock_write_unlock( & icmp_globals.lock );
/branches/network/uspace/srv/net/tl/udp/udp.c
49,6 → 49,7
#include "../../structures/dynamic_fifo.h"
#include "../../structures/packet/packet_client.h"
 
#include "../../include/crc.h"
#include "../../include/in.h"
#include "../../include/in6.h"
#include "../../include/inet.h"
57,6 → 58,7
#include "../../include/ip_protocols.h"
#include "../../include/icmp_client.h"
#include "../../include/icmp_interface.h"
#include "../../include/net_interface.h"
#include "../../include/socket_codes.h"
#include "../../include/socket_errno.h"
 
69,6 → 71,10
#include "udp_header.h"
#include "udp_module.h"
 
/** Default UDP checksum computing.
*/
#define NET_DEFAULT_UDP_CHECKSUM_COMPUTING true
 
/** Maximum UDP fragment size.
*/
#define MAX_UDP_FRAGMENT_SIZE 65535
163,24 → 169,12
* @returns ENOMEM if there is not enough memory left.
* @returns EINVAL if the received address is not an IP address.
* @returns Other error codes as defined for the packet_translate() function.
* @returns Other error codes as defined for the socket_write_data() function.
* @returns Other error codes as defined for the data_reply() function.
*/
int udp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen );
 
/*@}*/
 
/** Receives data from the socket.
* The received data buffer is allocated and returned.
* @param data The data buffer to be filled. Output parameter.
* @param length The buffer length. Output parameter.
* @returns EOK on success.
* @returns EBADMEM if the data or the length parameter is NULL.
* @returns EINVAL if the client does not send data.
* @returns ENOMEM if there is not enough memory left.
* @returns Other error codes as defined for the ipc_data_write_finalize() function.
*/
int socket_read_data( void ** data, size_t * length );
 
/** Receives data from the socket into a packet.
* @param packet The new created packet. Output parameter.
* @param prefix Reserved packet data prefix length. Input parameter.
193,15 → 187,6
*/
int socket_read_packet_data( packet_ref packet, size_t prefix, const struct sockaddr * addr, socklen_t addrlen );
 
/** Replies the data to the socket.
* @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 Other error codes as defined for the ipc_data_read_finalize() function.
*/
int socket_write_data( void * data, size_t data_length );
 
/** Sets the address port.
* Supports AF_INET and AF_INET6 address families.
* @param addr The address to be updated. Input/output parameter.
220,6 → 205,11
int udp_initialize( async_client_conn_t client_connection ){
ERROR_DECLARE;
 
measured_string_t names[] = {{ "UDP_CHECKSUM_COMPUTING", 22 }};
measured_string_ref configuration;
size_t count = sizeof( names ) / sizeof( measured_string_t );
char * data;
 
fibril_rwlock_initialize( & udp_globals.lock );
fibril_rwlock_write_lock( & udp_globals.lock );
udp_globals.icmp_phone = icmp_connect_module( SERVICE_ICMP );
235,6 → 225,16
udp_globals.prefix += sizeof( udp_header_t );
udp_globals.content -= sizeof( udp_header_t );
udp_globals.last_used_port = UDP_FREE_PORTS_START - 1;
// get configuration
udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING;
configuration = & names[ 0 ];
ERROR_PROPAGATE( net_get_conf_req( udp_globals.net_phone, & configuration, count, & data ));
if( configuration ){
if( configuration[ 0 ].value ){
udp_globals.checksum_computing = ( configuration[ 0 ].value[ 0 ] == 'y' );
}
net_free_settings( configuration, data );
}
fibril_rwlock_write_unlock( & udp_globals.lock );
return EOK;
}
250,11 → 250,14
socket_core_ref * socket;
packet_t next_packet;
size_t total_length;
// uint16_t checksum;
uint32_t checksum;
int fragments;
packet_t tmp_packet;
icmp_type_t type;
icmp_code_t code;
ip_pseudo_header_ref ip_header;
struct sockaddr * src;
struct sockaddr * dest;
 
if( error ){
switch( error ){
308,17 → 311,37
next_packet = packet;
fragments = 0;
total_length = ntohs( header->len );
// compute header checksum if set
if( header->check && ( ! error )){
result = packet_get_addr( packet, ( uint8_t ** ) & src, ( uint8_t ** ) & dest );
if( result <= 0 ){
return udp_release_and_return( packet, result );
}
if( ERROR_OCCURRED( ip_client_get_pseudo_header( IPPROTO_UDP, src, result, dest, result, total_length, & ip_header, & length ))){
return udp_release_and_return( packet, ERROR_CODE );
}else{
checksum = compute_checksum( 0, ip_header, length );
// the udp header checksum will be added with the first fragment later
free( ip_header );
}
}else{
header->check = 0;
checksum = 0;
}
do{
++ fragments;
length = packet_get_data_length( packet );
length = packet_get_data_length( next_packet );
if( length <= 0 ){
return udp_release_and_return( packet, NO_DATA );
}
if( total_length < length ){
// cut of the suffix if too long
if( ERROR_OCCURRED( packet_trim( next_packet, 0, length - total_length ))){
return udp_release_and_return( packet, ERROR_CODE );
}
// add partial checksum if set
if( header->check ){
checksum = compute_checksum( checksum, packet_get_data( packet ), packet_get_data_length( packet ));
}
// relese the rest of the packet fragments
tmp_packet = pq_next( next_packet );
while( tmp_packet ){
326,13 → 349,24
pq_release( udp_globals.net_phone, packet_get_id( tmp_packet ));
tmp_packet = next_packet;
}
// exit the loop
break;
}
total_length -= length;
/* if( header->header_checksum ){
// add partial checksum if set
if( header->check ){
checksum = compute_checksum( checksum, packet_get_data( packet ), packet_get_data_length( packet ));
}
*/
}while(( next_packet = pq_next( next_packet )) && ( total_length > 0 ));
// check checksum
if( header->check ){
if( flip_checksum( compact_checksum( checksum ))){
// TODO checksum error ICMP?
// TODO remove debug dump
printf("udp check failed %x => %x\n", header->check, flip_checksum( compact_checksum( checksum )));
return udp_release_and_return( packet, EINVAL );
}
}
// queue the received packet
if( ERROR_OCCURRED( dyn_fifo_push( &( ** socket ).received, packet_get_id( packet ), SOCKET_MAX_RECEIVED_SIZE ))){
return udp_release_and_return( packet, ERROR_CODE );
404,7 → 438,7
answer_count = 3;
break;
case NET_SOCKET_BIND:
res = socket_read_data(( void ** ) & addr, & addrlen );
res = data_receive(( void ** ) & addr, & addrlen );
if( res == EOK ){
fibril_rwlock_write_lock( & lock );
fibril_rwlock_write_lock( & udp_globals.lock );
415,7 → 449,7
}
break;
case NET_SOCKET_SENDTO:
res = socket_read_data(( void ** ) & addr, & addrlen );
res = data_receive(( void ** ) & addr, & addrlen );
if( res == EOK ){
fibril_rwlock_read_lock( & lock );
fibril_rwlock_read_lock( & udp_globals.lock );
475,6 → 509,10
size_t total_length;
int result;
uint16_t dest_port;
uint32_t checksum;
ip_pseudo_header_ref ip_header;
size_t headerlen;
device_id_t device_id;
 
if( addrlen < sizeof( struct sockaddr )) return EINVAL;
switch( addr->sa_family ){
510,18 → 548,23
}
 
// TODO do not ask all the time
ERROR_PROPAGATE( ip_packet_size_req( udp_globals.ip_phone, -1, & udp_globals.addr_len, & udp_globals.prefix, & udp_globals.content, & udp_globals.suffix ));
ERROR_PROPAGATE( ip_packet_size_req( udp_globals.ip_phone, socket->device_id, & udp_globals.addr_len, & udp_globals.prefix, & udp_globals.content, & udp_globals.suffix ));
 
// read the first packet fragment
result = socket_read_packet_data( & packet, sizeof( udp_header_t ), addr, addrlen );
if( result < 0 ) return result;
total_length = ( size_t ) result;
if( udp_globals.checksum_computing ){
checksum = compute_checksum( 0, packet_get_data( packet ), packet_get_data_length( packet ));
}else{
checksum = 0;
}
// prefix the udp header
header = PACKET_PREFIX( packet, udp_header_t );
if( ! header ){
pq_release( udp_globals.net_phone, packet_get_id( packet ));
return ENOMEM;
return udp_release_and_return( packet, ENOMEM );
}
bzero( header, sizeof( * header ));
// read the rest of the packet fragments
for( index = 1; index < fragments; ++ index ){
result = socket_read_packet_data( & next_packet, 0, addr, addrlen );
530,20 → 573,40
}
packet = pq_add( packet, next_packet, index, 0 );
total_length += ( size_t ) result;
if( udp_globals.checksum_computing ){
checksum = compute_checksum( checksum, packet_get_data( next_packet ), packet_get_data_length( next_packet ));
}
}
// set the udp header
header->source = htons( socket->port );
header->dest = htons( dest_port );
header->len = htons( total_length + sizeof( udp_header_t ));
// TODO my ip address for the pseudo header checksum
header->check = 0;
if( udp_globals.checksum_computing ){
if( ERROR_OCCURRED( ip_get_route_req( udp_globals.ip_phone, IPPROTO_UDP, addr, addrlen, & device_id, & ip_header, & headerlen ))){
return udp_release_and_return( packet, ERROR_CODE );
}
if( ERROR_OCCURRED( ip_client_set_pseudo_header_data_length( ip_header, headerlen, total_length + sizeof( udp_header_t )))){
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, ( uint8_t * ) header, sizeof( * header ));
header->check = htons( flip_checksum( compact_checksum( checksum )));
free( ip_header );
}else{
device_id = socket->device_id;
}
// prepare the first packet fragment
if( ERROR_OCCURRED( ip_client_prepare_packet( packet, IPPROTO_UDP, 0, 0, 0, 0 ))){
pq_release( udp_globals.net_phone, packet_get_id( packet ));
return ERROR_CODE;
return udp_release_and_return( packet, ERROR_CODE );
}
// send the packet
return ip_send_msg( udp_globals.ip_phone, socket->device_id, packet, SERVICE_UDP, 0 );
return ip_send_msg( udp_globals.ip_phone, device_id, packet, SERVICE_UDP, 0 );
}
 
int udp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen ){
585,12 → 648,12
}
* addrlen = ( size_t ) result;
// send the source address
ERROR_PROPAGATE( socket_write_data( addr, * addrlen ));
ERROR_PROPAGATE( data_reply( addr, * addrlen ));
 
next_packet = pq_next( packet );
if( ! next_packet ){
// write all if only one fragment
ERROR_PROPAGATE( socket_write_data( data + sizeof( udp_header_t ), packet_get_data_length( packet ) - sizeof( udp_header_t )));
ERROR_PROPAGATE( data_reply( data + sizeof( udp_header_t ), packet_get_data_length( packet ) - sizeof( udp_header_t )));
// store the total length
length = packet_get_data_length( packet ) - sizeof( udp_header_t );
}else{
612,13 → 675,13
next_packet = pq_next( packet );
}while( next_packet );
// write the fragment lengths
ERROR_PROPAGATE( socket_write_data( lengths, sizeof( int ) * ( fragments + 1 )));
ERROR_PROPAGATE( data_reply( lengths, sizeof( int ) * ( fragments + 1 )));
// write the first fragment
ERROR_PROPAGATE( socket_write_data( data + sizeof( udp_header_t ), lengths[ 0 ] ));
ERROR_PROPAGATE( data_reply( data + sizeof( udp_header_t ), lengths[ 0 ] ));
next_packet = pq_next( packet );
// write the rest of the fragments
for( index = 1; index < fragments; ++ index ){
ERROR_PROPAGATE( socket_write_data( packet_get_data( next_packet ), lengths[ index ] ));
ERROR_PROPAGATE( data_reply( packet_get_data( next_packet ), lengths[ index ] ));
next_packet = pq_next( packet );
}while( next_packet );
// store the total length
632,33 → 695,6
return ( int ) length;
}
 
int socket_write_data( void * data, size_t data_length ){
size_t length;
ipc_callid_t callid;
 
if(( ! ipc_data_read_receive( & callid, & length ))
|| ( length < data_length )){
return EINVAL;
}
return ipc_data_read_finalize( callid, data, data_length );
}
 
int socket_read_data( void ** data, size_t * length ){
ERROR_DECLARE;
 
ipc_callid_t callid;
 
if( !( data && length )) return EBADMEM;
if( ! ipc_data_write_receive( & callid, length )) return EINVAL;
* data = malloc( * length );
if( !( * data )) return ENOMEM;
if( ERROR_OCCURRED( ipc_data_write_finalize( callid, * data, * length ))){
free( data );
return ERROR_CODE;
}
return EOK;
}
 
int socket_read_packet_data( packet_ref packet, size_t prefix, const struct sockaddr * addr, socklen_t addrlen ){
ERROR_DECLARE;
 
674,15 → 710,13
// allocate space in the packet
data = packet_suffix( * packet, length );
if( ! data ){
pq_release( udp_globals.net_phone, packet_get_id( * packet ));
return ENOMEM;
return udp_release_and_return( * packet, ENOMEM );
}
// read the data into the packet
if( ERROR_OCCURRED( ipc_data_write_finalize( callid, data, length ))
// set the packet destination address
|| ERROR_OCCURRED( packet_set_addr( * packet, NULL, ( uint8_t * ) addr, addrlen ))){
pq_release( udp_globals.net_phone, packet_get_id( * packet ));
return ERROR_CODE;
return udp_release_and_return( * packet, ERROR_CODE );
}
return ( int ) length;
}
/branches/network/uspace/srv/net/tl/udp/Makefile
38,6 → 38,7
SOURCES = \
$(NAME).c \
$(NAME)_module.c \
$(NET_BASE)crc.c \
$(NET_BASE)module.c \
$(NET_BASE)modules.c \
$(NET_BASE)il/ip/ip_client.c \
/branches/network/uspace/srv/net/tl/udp/udp.h
70,6 → 70,9
/** Packet address length.
*/
size_t addr_len;
/** Indicates whether UDP checksum computing is enabled.
*/
int checksum_computing;
/** Last used free port.
*/
int last_used_port;
/branches/network/uspace/srv/net/nil/eth/eth.c
324,7 → 324,11
return EEXIST;
}else{
// update mtu
device->mtu = mtu;
if(( mtu > 0 ) && ( mtu <= ETH_MAX_TAGGED_CONTENT( device->flags ))){
device->mtu = mtu;
}else{
device->mtu = ETH_MAX_TAGGED_CONTENT( device->flags );
}
printf( "Device %d already exists:\tMTU\t= %d\n", device->device_id, device->mtu );
fibril_rwlock_write_unlock( & eth_globals.devices_lock );
// notify all upper layer modules
345,7 → 349,11
device->device_id = device_id;
device->service = service;
device->flags = 0;
device->mtu = (( mtu > 0 ) && ( mtu <= ETH_MAX_TAGGED_CONTENT( device->flags ))) ? mtu : ETH_MAX_TAGGED_CONTENT( device->flags );
if(( mtu > 0 ) && ( mtu <= ETH_MAX_TAGGED_CONTENT( device->flags ))){
device->mtu = mtu;
}else{
device->mtu = ETH_MAX_TAGGED_CONTENT( device->flags );
}
configuration = & names[ 0 ];
if( ERROR_OCCURRED( net_get_device_conf_req( eth_globals.net_phone, device->device_id, & configuration, count, & data ))){
fibril_rwlock_write_unlock( & eth_globals.devices_lock );
/branches/network/uspace/srv/net/nil/nildummy/nildummy.c
62,7 → 62,7
 
/** Default maximum transmission unit.
*/
#define DEFAULT_MTU 1500
#define NET_DEFAULT_MTU 1500
 
/** Network interface layer module global data.
*/
174,7 → 174,11
return EEXIST;
}else{
// update mtu
device->mtu = mtu;
if( mtu > 0 ){
device->mtu = mtu;
}else{
device->mtu = NET_DEFAULT_MTU;
}
printf( "Device %d already exists:\tMTU\t= %d\n", device->device_id, device->mtu );
fibril_rwlock_write_unlock( & nildummy_globals.devices_lock );
// notify the upper layer module
194,7 → 198,7
if( mtu > 0 ){
device->mtu = mtu;
}else{
device->mtu = DEFAULT_MTU;
device->mtu = NET_DEFAULT_MTU;
}
// bind the device driver
device->phone = netif_bind_service( device->service, device->device_id, SERVICE_ETHERNET, nildummy_receiver );
/branches/network/uspace/srv/net/include/ip_client.h
42,6 → 42,8
#include "../structures/packet/packet.h"
 
#include "ip_codes.h"
#include "ip_interface.h"
#include "socket_codes.h"
 
int ip_client_prepare_packet( packet_t packet, ip_protocol_t protocol, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, size_t ipopt_length );
 
54,6 → 56,14
*/
size_t ip_client_header_length( packet_t packet );
 
/** \todo
*/
int ip_client_set_pseudo_header_data_length( ip_pseudo_header_ref header, size_t headerlen, size_t data_length );
 
/** \todo
*/
int ip_client_get_pseudo_header( ip_protocol_t protocol, struct sockaddr * src, socklen_t srclen, struct sockaddr * dest, socklen_t destlen, size_t data_length, ip_pseudo_header_ref * header, size_t * headerlen );
 
// TODO ipopt manipulation
 
#endif
/branches/network/uspace/srv/net/include/crc.h
84,10 → 84,17
*/
uint16_t compact_checksum( uint32_t sum );
 
/** Returns or flips the checksum if zero.
* @param checksum The computed checksum. Input parameter.
* @returns The internet protocol header checksum.
* @returns 0xFFFF if the computed checksum is zero.
*/
uint16_t flip_checksum( uint16_t checksum );
 
/** Computes the ip header checksum.
* To compute the checksum of a new packet, the checksum header field must be zero.
* To check the checksum of a received packet, the checksum may be left set.
* The zero (0) value will returned in this case if valid.
* The zero (0) value will be returned in this case if valid.
* @param data The header data. Input parameter.
* @param length The header length in bytes. Input parameter.
* @returns The internet protocol header checksum.
/branches/network/uspace/srv/net/include/ip_interface.h
49,6 → 49,8
#include "../structures/packet/packet.h"
 
#include "in.h"
#include "ip_codes.h"
#include "socket_codes.h"
 
/** @name IP module interface
* This interface is used by other modules.
55,6 → 57,10
*/
/*@{*/
 
/** Type definition of the internet pseudo header pointer.
*/
typedef void * ip_pseudo_header_ref;
 
/** The transport layer notification function type definition.
* Notifies the transport layer modules about the received packet/s.
* @param device_id The device identifier. Input parameter.
153,6 → 159,10
*/
int ip_received_error_msg( int ip_phone, device_id_t device_id, packet_t packet, services_t target, services_t error );
 
/** \todo
*/
int ip_get_route_req( int ip_phone, ip_protocol_t protocol, const struct sockaddr * destination, socklen_t addrlen, device_id_t * device_id, ip_pseudo_header_ref * header, size_t * headerlen );
 
/*@}*/
 
#endif
/branches/network/uspace/srv/net/net/net.c
350,6 → 350,7
ERROR_PROPAGATE( add_configuration( & net_globals.configuration, "MTU", "1500" ));
ERROR_PROPAGATE( add_configuration( & net_globals.configuration, "ICMP_ERROR_REPORTING", "yes" )); //anything else not starting with 'y'
ERROR_PROPAGATE( add_configuration( & net_globals.configuration, "ICMP_ECHO_REPLYING", "yes" )); //anything else not starting with 'y'
ERROR_PROPAGATE( add_configuration( & net_globals.configuration, "UDP_CHECKSUM_COMPUTING", "yes" )); //anything else not starting with 'y'
return EOK;
}
 
/branches/network/uspace/srv/net/crc.c
128,14 → 128,14
return ( uint16_t ) sum;
}
 
uint16_t ip_checksum( uint8_t * data, size_t length ){
uint16_t checksum;
 
checksum = compact_checksum(compute_checksum( 0, data, length ));
 
uint16_t flip_checksum( uint16_t checksum ){
// flip, zero is returned as 0xFFFF (not flipped)
return ( ~ checksum ) ? ( uint16_t ) ( ~ checksum ) : IP_CHECKSUM_ZERO;
}
 
uint16_t ip_checksum( uint8_t * data, size_t length ){
return flip_checksum( compact_checksum( compute_checksum( 0, data, length )));
}
 
/** @}
*/
/branches/network/uspace/srv/net/modules.c
33,7 → 33,9
/** @file
* Generic module functions implementation.
*/
 
#include <async.h>
#include <malloc.h>
 
#include <ipc/ipc.h>
#include <ipc/services.h>
117,5 → 119,32
}
}
 
int data_receive( void ** data, size_t * length ){
ERROR_DECLARE;
 
ipc_callid_t callid;
 
if( !( data && length )) return EBADMEM;
if( ! ipc_data_write_receive( & callid, length )) return EINVAL;
* data = malloc( * length );
if( !( * data )) return ENOMEM;
if( ERROR_OCCURRED( ipc_data_write_finalize( callid, * data, * length ))){
free( data );
return ERROR_CODE;
}
return EOK;
}
 
int data_reply( void * data, size_t data_length ){
size_t length;
ipc_callid_t callid;
 
if(( ! ipc_data_read_receive( & callid, & length ))
|| ( length < data_length )){
return EINVAL;
}
return ipc_data_read_finalize( callid, data, data_length );
}
 
/** @}
*/
/branches/network/uspace/srv/net/messages.h
52,7 → 52,7
#define NET_NIL_COUNT 7
#define NET_ETH_COUNT 0
#define NET_IL_COUNT 6
#define NET_IP_COUNT 3
#define NET_IP_COUNT 4
#define NET_ARP_COUNT 5
#define NET_RARP_COUNT 0
#define NET_ICMP_COUNT 7
145,6 → 145,8
 
#define IPC_GET_PHONE( call ) ( int ) IPC_GET_ARG5( * call )
 
#define IPC_SET_DEVICE( answer ) (( device_id_t * ) & IPC_GET_ARG1( * answer ))
 
#define IPC_SET_ADDR( answer ) (( size_t * ) & IPC_GET_ARG1( * answer ))
#define IPC_SET_PREFIX( answer ) (( size_t * ) & IPC_GET_ARG2( * answer ))
#define IPC_SET_CONTENT( answer ) (( size_t * ) & IPC_GET_ARG3( * answer ))
/branches/network/uspace/srv/net/modules.h
93,6 → 93,27
*/
void refresh_answer( ipc_call_t * answer, int * answer_count );
 
/** Receives data from the other party.
* The received data buffer is allocated and returned.
* @param data The data buffer to be filled. Output parameter.
* @param length The buffer length. Output parameter.
* @returns EOK on success.
* @returns EBADMEM if the data or the length parameter is NULL.
* @returns EINVAL if the client does not send data.
* @returns ENOMEM if there is not enough memory left.
* @returns Other error codes as defined for the ipc_data_write_finalize() function.
*/
int data_receive( void ** data, size_t * length );
 
/** Replies the data to the other party.
* @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 Other error codes as defined for the ipc_data_read_finalize() function.
*/
int data_reply( void * data, size_t data_length );
 
#endif
 
/** @}
/branches/network/uspace/srv/net/il/ip/ip_remote.c
83,5 → 83,33
return generic_received_msg( ip_phone, NET_IP_RECEIVED_ERROR, device_id, packet_get_id( packet ), target, error );
}
 
int ip_get_route_req( int ip_phone, ip_protocol_t protocol, const struct sockaddr * destination, socklen_t addrlen, device_id_t * device_id, ip_pseudo_header_ref * header, size_t * headerlen ){
aid_t message_id;
ipcarg_t result;
ipc_call_t answer;
 
if( !( destination && ( addrlen > 0 ))) return EINVAL;
if( !( device_id && header && headerlen )) return EBADMEM;
* header = NULL;
message_id = async_send_1( ip_phone, NET_IP_GET_ROUTE, ( ipcarg_t ) protocol, & answer );
if(( ipc_data_write_start( ip_phone, destination, addrlen ) == EOK )
&& ( ipc_data_read_start( ip_phone, headerlen, sizeof( * headerlen )) == EOK )
&& ( * headerlen > 0 )){
* header = ( ip_pseudo_header_ref ) malloc( * headerlen );
if( * header ){
if( ipc_data_read_start( ip_phone, * header, * headerlen ) != EOK ){
free( * header );
}
}
}
async_wait_for( message_id, & result );
if(( result != EOK ) && ( * header )){
free( * header );
}else{
* device_id = IPC_GET_DEVICE( & answer );
}
return ( int ) result;
}
 
/** @}
*/
/branches/network/uspace/srv/net/il/ip/ip_messages.h
40,6 → 40,9
 
#include <ipc/ipc.h>
 
#include "../../include/in.h"
#include "../../include/ip_codes.h"
 
/** IP module messages.
*/
typedef enum{
54,7 → 57,11
/** Processes the received error notification.
* @see ip_received_error_msg()
*/
NET_IP_RECEIVED_ERROR
NET_IP_RECEIVED_ERROR,
/** Gets the actual route information.
* @see ip_get_route()
*/
NET_IP_GET_ROUTE
} ip_messages;
 
/** @name IP specific message parameters definitions
76,6 → 83,17
*/
#define IP_GET_NETMASK( call ) ({ in_addr_t addr; addr.s_addr = IPC_GET_ARG4( * call ); addr; })
 
/** Returns the protocol message parameter.
* @param call The message call structure. Input parameter.
*/
#define IP_GET_PROTOCOL( call ) (( ip_protocol_t ) IPC_GET_ARG1( * call ))
 
/** Sets the header length in the message answer.
* @param answer The message answer structure. Output parameter.
*/
#define IP_SET_HEADERLEN( answer ) (( size_t * ) & IPC_GET_ARG2( * answer ))
 
 
/*@}*/
 
#endif
/branches/network/uspace/srv/net/il/ip/ip_header.h
208,6 → 208,36
#define MAX_IPOPTLEN 40
*/
 
/** Type definition of the internet version 4 pseudo header.
* @see ipv4_pseudo_header
*/
typedef struct ipv4_pseudo_header ipv4_pseudo_header_t;
 
/** Type definition of the internet version 4 pseudo header pointer.
* @see ipv4_pseudo_header
*/
typedef ipv4_pseudo_header_t * ipv4_pseudo_header_ref;
 
/** Internet version 4 pseudo header.
*/
struct ipv4_pseudo_header{
/** The source address.
*/
uint32_t source_address;
/** The destination address.
*/
uint32_t destination_address;
/** Zero byte.
*/
uint8_t zero;
/** This field indicates the next level protocol used in the data portion of the internet datagram.
*/
uint8_t protocol;
/** Data length is the length of the datagram, measured in octets.
*/
uint16_t data_length;
} __attribute__ ((packed));
 
#endif
 
/** @}
/branches/network/uspace/srv/net/il/ip/ip_client.c
40,6 → 40,7
#include <sys/types.h>
 
#include "../../include/ip_client.h"
#include "../../include/socket_errno.h"
 
#include "../../structures/packet/packet.h"
#include "../../structures/packet/packet_client.h"
99,5 → 100,48
return header->ihl * 4u;
}
 
int ip_client_set_pseudo_header_data_length( ip_pseudo_header_ref header, size_t headerlen, size_t data_length ){
ipv4_pseudo_header_ref header_in;
 
if( headerlen == sizeof( ipv4_pseudo_header_t )){
header_in = ( ipv4_pseudo_header_ref ) header;
header_in->data_length = htons( data_length );
return EOK;
}else{
return EINVAL;
}
}
 
int ip_client_get_pseudo_header( ip_protocol_t protocol, struct sockaddr * src, socklen_t srclen, struct sockaddr * dest, socklen_t destlen, size_t data_length, ip_pseudo_header_ref * header, size_t * headerlen ){
ipv4_pseudo_header_ref header_in;
struct sockaddr_in * address_in;
 
if( !( header && headerlen )) return EBADMEM;
if( !( src && dest && ( srclen >= sizeof( struct sockaddr )) && ( srclen == destlen ) && ( src->sa_family == dest->sa_family ))) return EINVAL;
switch( src->sa_family ){
case AF_INET:
if( srclen != sizeof( struct sockaddr_in )) return EINVAL;
* headerlen = sizeof( * header_in );
header_in = ( ipv4_pseudo_header_ref ) malloc( * headerlen );
if( ! header_in ) return ENOMEM;
bzero( header_in, * headerlen );
address_in = ( struct sockaddr_in * ) dest;
header_in->destination_address = address_in->sin_addr.s_addr;
address_in = ( struct sockaddr_in * ) src;
header_in->source_address = address_in->sin_addr.s_addr;
header_in->protocol = protocol;
header_in->data_length = htons( data_length );
* header = ( ip_pseudo_header_ref ) header_in;
return EOK;
// TODO IPv6
/* case AF_INET6:
if( addrlen != sizeof( struct sockaddr_in6 )) return EINVAL;
address_in6 = ( struct sockaddr_in6 * ) addr;
return EOK;
*/ default:
return EAFNOSUPPORT;
}
}
 
/** @}
*/
/branches/network/uspace/srv/net/il/ip/ip.c
82,10 → 82,18
#include "ip_messages.h"
#include "ip_module.h"
 
/** Default IP version.
/** IP version 4.
*/
#define DEFAULT_IPV 4
#define IPV4 4
 
/** Default network interface IP version.
*/
#define NET_DEFAULT_IPV IPV4
 
/** Default network interface IP routing.
*/
#define NET_DEFAULT_IP_ROUTING false
 
/** Minimum IP packet content.
*/
#define IP_MIN_CONTENT 576
134,6 → 142,11
*/
#define IP_HEADER_CHECKSUM( header ) ( htons( ip_checksum(( uint8_t * )( header ), IP_HEADER_LENGTH( header ))))
 
/** Returns the fragment offest.
* @param length The prefixed data total length. Input parameter.
*/
#define IP_FRAGMENT_OFFSET( length ) (( length ) / 8 )
 
/** IP global data.
*/
ip_globals_t ip_globals;
304,6 → 317,9
 
ip_netif->arp = NULL;
route = NULL;
ip_netif->ipv = NET_DEFAULT_IPV;
ip_netif->dhcp = false;
ip_netif->routing = NET_DEFAULT_IP_ROUTING;
configuration = & names[ 0 ];
// get configuration
ERROR_PROPAGATE( net_get_device_conf_req( ip_globals.net_phone, ip_netif->device_id, & configuration, count, & data ));
310,8 → 326,6
if( configuration ){
if( configuration[ 0 ].value ){
ip_netif->ipv = strtol( configuration[ 0 ].value, NULL, 0 );
}else{
ip_netif->ipv = DEFAULT_IPV;
}
ip_netif->dhcp = ! str_lcmp( configuration[ 1 ].value, "dhcp", configuration[ 1 ].length );
if( ip_netif->dhcp ){
318,7 → 332,7
// TODO dhcp
net_free_settings( configuration, data );
return ENOTSUP;
}else if( ip_netif->ipv == 4 ){
}else if( ip_netif->ipv == IPV4 ){
route = ( ip_route_ref ) malloc( sizeof( ip_route_t ));
if( ! route ){
net_free_settings( configuration, data );
355,10 → 369,10
net_free_settings( configuration, data );
return EINVAL;
}
}else{
ip_netif->arp = NULL;
}
ip_netif->routing = configuration[ 9 ].value && ( configuration[ 9 ].value[ 0 ] == 'y' );
if( configuration[ 9 ].value ){
ip_netif->routing = ( configuration[ 9 ].value[ 0 ] == 'y' );
}
net_free_settings( configuration, data );
}
// binds the netif service which also initializes the device
598,7 → 612,7
int phone;
 
// get destination hardware address
if( netif->arp ){
if( netif->arp && ( route->address.s_addr != dest.s_addr )){
destination.value = route->gateway.s_addr ? ( char * ) & route->gateway.s_addr : ( char * ) & dest.s_addr;
destination.length = CONVERT_SIZE( dest.s_addr, char, 1 );
if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ))){
649,8 → 663,10
header = ( ip_header_ref ) packet_get_data( packet );
if( destination ){
ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
}else{
ERROR_PROPAGATE( packet_set_addr( packet, NULL, NULL, 0 ));
}
header->version = 4;
header->version = IPV4;
header->fragment_offset = 0;
header->header_checksum = 0;
if( source ) header->source_address = source->s_addr;
671,7 → 687,7
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->fragment_offset = IP_FRAGMENT_OFFSET( 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 )));
683,7 → 699,7
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->fragment_offset = IP_FRAGMENT_OFFSET( 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 )));
701,7 → 717,11
int ip_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
ERROR_DECLARE;
 
packet_t packet;
packet_t packet;
struct sockaddr * addr;
size_t addrlen;
ip_pseudo_header_ref header;
size_t headerlen;
 
* answer_count = 0;
switch( IPC_GET_METHOD( * call )){
726,6 → 746,15
return ip_add_route_req( 0, IPC_GET_DEVICE( call ), IP_GET_ADDRESS( call ), IP_GET_NETMASK( call ), IP_GET_GATEWAY( call ));
case NET_IP_SET_GATEWAY:
return ip_set_gateway_req( 0, IPC_GET_DEVICE( call ), IP_GET_GATEWAY( call ));
case NET_IP_GET_ROUTE:
ERROR_PROPAGATE( data_receive(( void ** ) & addr, & addrlen ));
ERROR_PROPAGATE( ip_get_route_req( 0, IP_GET_PROTOCOL( call ), addr, ( socklen_t ) addrlen, IPC_SET_DEVICE( answer ), & header, & headerlen ));
* IP_SET_HEADERLEN( answer ) = headerlen;
if( ! ERROR_OCCURRED( data_reply( & headerlen, sizeof( headerlen )))){
ERROR_CODE = data_reply( header, headerlen );
}
free( header );
return ERROR_CODE;
case NET_IL_PACKET_SPACE:
ERROR_PROPAGATE( ip_packet_size_req( 0, IPC_GET_DEVICE( call ), IPC_SET_ADDR( answer ), IPC_SET_PREFIX( answer ), IPC_SET_CONTENT( answer ), IPC_SET_SUFFIX( answer )));
* answer_count = 3;
1285,5 → 1314,55
return result;
}
 
int ip_get_route_req( int ip_phone, ip_protocol_t protocol, const struct sockaddr * destination, socklen_t addrlen, device_id_t * device_id, ip_pseudo_header_ref * header, size_t * headerlen ){
struct sockaddr_in * address_in;
// struct sockaddr_in6 * address_in6;
in_addr_t * dest;
in_addr_t * src;
ip_route_ref route;
ipv4_pseudo_header_ref header_in;
 
if( !( destination && ( addrlen > 0 ))) return EINVAL;
if( !( device_id && header && headerlen )) return EBADMEM;
if( addrlen < sizeof( struct sockaddr )){
return EINVAL;
}
switch( destination->sa_family ){
case AF_INET:
if( addrlen != sizeof( struct sockaddr_in )){
return EINVAL;
}
address_in = ( struct sockaddr_in * ) destination;
dest = & address_in->sin_addr;
break;
// TODO IPv6
/* case AF_INET6:
if( addrlen != sizeof( struct sockaddr_in6 )) return EINVAL;
address_in6 = ( struct sockaddr_in6 * ) dest;
address_in6.sin6_addr.s6_addr;
*/ default:
return EAFNOSUPPORT;
}
fibril_rwlock_read_lock( & ip_globals.lock );
route = ip_find_route( * dest );
if( !( route && route->netif )){
fibril_rwlock_read_unlock( & ip_globals.lock );
return ENOENT;
}
* device_id = route->netif->device_id;
src = ip_netif_address( route->netif );
fibril_rwlock_read_unlock( & ip_globals.lock );
* headerlen = sizeof( * header_in );
header_in = ( ipv4_pseudo_header_ref ) malloc( * headerlen );
if( ! header_in ) return ENOMEM;
bzero( header_in, * headerlen );
header_in->destination_address = dest->s_addr;
header_in->source_address = src->s_addr;
header_in->protocol = protocol;
header_in->data_length = 0;
* header = ( ip_pseudo_header_ref ) header_in;
return EOK;
}
 
/** @}
*/
/branches/network/uspace/srv/net/netif/lo/lo.c
51,7 → 51,6
 
#include "../../include/device.h"
#include "../../include/nil_interface.h"
#include "../../include/net_interface.h"
 
#include "../../nil/nil_messages.h"