Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4721 → Rev 4722

/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;
}
 
/** @}
*/