/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,13 → 508,15 |
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; |
} |
} |
int icmp_initialize( async_client_conn_t client_connection ){ |
ERROR_DECLARE; |
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 |
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 |
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 ))); |
702,6 → 718,10 |
ERROR_DECLARE; |
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" |