Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4721 → Rev 4722

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