Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4557 → Rev 4558

/branches/network/uspace/srv/net/il/ip/ip.c
35,6 → 35,7
 
#include <async.h>
#include <errno.h>
#include <rwlock.h>
#include <stdio.h>
#include <string.h>
 
48,7 → 49,7
#include "../../modules.h"
 
#include "../../include/net_interface.h"
#include "../../include/sockaddr.h"
#include "../../include/inet.h"
#include "../../include/socket.h"
#include "../../include/byteorder.h"
#include "../../include/crc.h"
82,13 → 83,13
#define IP_PREFIX sizeof( ip_header_t )
#define IP_SUFFIX 0
#define IP_MAX_CONTENT 65535
#define IP_HEADER_LENGTH( header ) (( header )->ihl * 4 )
#define IP_HEADER_LENGTH( header ) (( header )->ihl * 4u )
#define IP_TOTAL_LENGTH( header ) ntohs(( header )->total_length )
#define IP_HEADER_DATA_LENGTH( header ) ( IP_TOTAL_LENGTH( header ) - IP_HEADER_LENGTH( header ))
#define IP_HEADER_CHECKSUM( header ) ( htons( ip_checksum(( uint8_t * )( header ), IP_HEADER_LENGTH( header ))))
 
//zero is returned as 0xFFFF (not flipped)
#define IP_HEADER_CHECKSUM_ZERO 0xFFFF
#define IP_HEADER_CHECKSUM_ZERO 0xFFFFu
 
ip_globals_t ip_globals;
 
127,11 → 128,11
* @param data The header data. Input parameter.
* @param length The header length in bytes. Input parameter.
* @returns The internet protocol header checksum.
* @returns IP_HEADER_CHECKSUM_ZERO if the computed checksum is zero.
* @returns 0xFFFF if the computed checksum is zero.
*/
uint16_t ip_checksum( uint8_t * data, int length );
uint16_t ip_checksum( uint8_t * data, size_t length );
 
uint16_t ip_checksum( uint8_t * data, int length ){
uint16_t ip_checksum( uint8_t * data, size_t length ){
uint16_t checksum;
 
checksum = compact_checksum(compute_checksum( 0, data, length ));
145,6 → 146,10
int ip_initialize( async_client_conn_t client_connection ){
ERROR_DECLARE;
 
rwlock_initialize( & ip_globals.lock );
rwlock_write_lock( & ip_globals.lock );
rwlock_initialize( & ip_globals.protos_lock );
rwlock_initialize( & ip_globals.netifs_lock );
ip_globals.packet_counter = 0;
ip_globals.gateway.address.s_addr = 0;
ip_globals.gateway.netmask.s_addr = 0;
155,6 → 160,7
ip_globals.client_connection = client_connection;
ERROR_PROPAGATE( modules_initialize( & ip_globals.modules ));
ERROR_PROPAGATE( add_module( NULL, & ip_globals.modules, ARP_NAME, ARP_FILENAME, SERVICE_ARP, arp_task_get_id(), arp_connect_module ));
rwlock_write_unlock( & ip_globals.lock );
return EOK;
}
 
175,7 → 181,9
ip_netif->device_id = device_id;
ip_netif->service = netif;
ip_netif->state = NETIF_STOPPED;
rwlock_write_lock( & ip_globals.netifs_lock );
if( ERROR_OCCURRED( ip_netif_initialize( ip_netif ))){
rwlock_write_unlock( & ip_globals.netifs_lock );
ip_routes_destroy( & ip_netif->routes );
free( ip_netif );
return ERROR_CODE;
207,6 → 215,7
printf( "\tdns2\t= %s\n", data );
free( data );
}
rwlock_write_unlock( & ip_globals.netifs_lock );
return EOK;
}
 
279,7 → 288,7
}
net_free_settings( configuration, data );
}
ip_netif->phone = bind_service( ip_netif->service, ip_netif->device_id, SERVICE_IP, 0, ip_globals.client_connection );
ip_netif->phone = bind_service( ip_netif->service, ( ipcarg_t ) ip_netif->device_id, SERVICE_IP, 0, ip_globals.client_connection );
if( ip_netif->phone < 0 ){
printf( "Failed to contact the nil service %d\n", ip_netif->service );
return ip_netif->phone;
324,11 → 333,16
*/
ip_netif_ref netif;
 
rwlock_write_lock( & ip_globals.netifs_lock );
netif = ip_netifs_find( & ip_globals.netifs, device_id );
if( ! netif ) return ENOENT;
if( ! netif ){
rwlock_write_unlock( & ip_globals.netifs_lock );
return ENOENT;
}
netif->state = state;
// TODO state
printf( "ip - device %d changed state to %d\n\n", device_id, state );
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 );
377,27 → 391,30
return EOK;
}
 
int ip_bind_service( services_t service, int protocol, services_t me, async_client_conn_t receiver, tl_received_msg_t tl_received_msg ){
return ip_register( protocol, me, 0, tl_received_msg );
int ip_bind_service( services_t service, int protocol, services_t me, async_client_conn_t receiver, tl_received_msg_t received_msg ){
return ip_register( protocol, me, 0, received_msg );
}
 
int ip_register( int protocol, services_t service, int phone, tl_received_msg_t tl_received_msg ){
int ip_register( int protocol, services_t service, int phone, tl_received_msg_t received_msg ){
ip_proto_ref proto;
int index;
 
if( !( protocol && service && (( phone > 0 ) || ( tl_received_msg )))) return EINVAL;
if( !( protocol && service && (( phone > 0 ) || ( received_msg )))) return EINVAL;
proto = ( ip_proto_ref ) malloc( sizeof( ip_protos_t ));
if( ! proto ) return ENOMEM;
proto->protocol = protocol;
proto->service = service;
proto->phone = phone;
proto->tl_received_msg = tl_received_msg;
proto->received_msg = received_msg;
rwlock_write_lock( & ip_globals.protos_lock );
index = ip_protos_add( & ip_globals.protos, proto->protocol, proto );
if( index < 0 ){
rwlock_write_unlock( & ip_globals.protos_lock );
free( proto );
return index;
}
printf( "New protocol registered:\n\tprotocol\t= %d\n\tphone\t= %d\n", proto->protocol, proto->phone );
rwlock_write_unlock( & ip_globals.protos_lock );
return EOK;
}
 
422,7 → 439,7
pq_release( ip_globals.net_phone, packet_get_id( packet ));
return EINVAL;
}
// rwlock_read_lock( & ip_globals.devices_lock );
rwlock_read_lock( & ip_globals.netifs_lock );
// device specified?
// dest.s_addr = ntohl( dest.s_addr );
if( device_id ){
434,7 → 451,7
netif = route ? route->netif : NULL;
}
if( !( netif && route )){
// rwlock_read_unlock( & ip_globals.devices_lock );
rwlock_read_unlock( & ip_globals.netifs_lock );
pq_release( ip_globals.net_phone, packet_get_id( packet ));
return ENOENT;
}
441,10 → 458,13
// to me?
if( route->address.s_addr == dest.s_addr ){
// TODO loopback deliver
rwlock_read_unlock( & ip_globals.netifs_lock );
return ip_deliver_local( -1, packet, ( ip_header_ref ) packet_get_data( packet ));
}
 
src = ip_netif_addr( netif );
if( ! src ){
rwlock_read_unlock( & ip_globals.netifs_lock );
pq_release( ip_globals.net_phone, packet_get_id( packet ));
return ENOENT;
}
451,6 → 471,7
if( ERROR_OCCURRED( ip_send_route( packet, netif, route, src, dest ))){
pq_release( ip_globals.net_phone, packet_get_id( packet ));
}
rwlock_read_unlock( & ip_globals.netifs_lock );
return ERROR_CODE;
}
 
514,7 → 535,6
nil_send_msg( netif->phone, netif->device_id, packet, SERVICE_IP );
}
}
// rwlock_read_unlock( & ip_globals.netifs_lock );
return EOK;
}
 
521,7 → 541,7
int ip_prepare_packet( in_addr_t * source, packet_t packet, measured_string_ref destination ){
ERROR_DECLARE;
 
int length;
size_t length;
ip_header_ref header;
 
length = packet_get_data_length( packet );
534,8 → 554,10
header->total_length = htons( length );
header->fragment_offset = 0;
if( source ) header->source_address = source->s_addr;//htonl( source.s_addr );
rwlock_write_lock( & ip_globals.lock );
++ ip_globals.packet_counter;
header->identification = htons( ip_globals.packet_counter );
rwlock_write_unlock( & ip_globals.lock );
header->header_checksum = 0;
// unnecessary for all protocols
header->header_checksum = IP_HEADER_CHECKSUM( header );
581,10 → 603,10
ip_netif_ref netif;
 
if( !( addr_len && prefix && content && suffix )) return EBADMEM;
// rwlock_read_lock( & ip_globals.netifs_lock );
rwlock_read_lock( & ip_globals.netifs_lock );
netif = ip_netifs_find( & ip_globals.netifs, device_id );
if( ! netif ){
// rwlock_read_unlock( & ip_globals.netifs_lock );
rwlock_read_unlock( & ip_globals.netifs_lock );
return ENOENT;
}
* content = IP_MAX_CONTENT - IP_PREFIX;
591,7 → 613,7
* addr_len = ( netif->addr_len > IP_ADDR ) ? netif->addr_len : IP_ADDR;
* prefix = netif->prefix + IP_PREFIX;
* suffix = netif->suffix + IP_SUFFIX;
// rwlock_read_unlock( & ip_globals.netifs_lock );
rwlock_read_unlock( & ip_globals.netifs_lock );
return EOK;
}
 
600,10 → 622,17
ip_netif_ref netif;
int index;
 
rwlock_write_lock( & ip_globals.netifs_lock );
netif = ip_netifs_find( & ip_globals.netifs, device_id );
if( ! netif ) return ENOENT;
if( ! netif ){
rwlock_write_unlock( & ip_globals.netifs_lock );
return ENOENT;
}
route = ( ip_route_ref ) malloc( sizeof( ip_route_t ));
if( ! route ) return ENOMEM;
if( ! route ){
rwlock_write_unlock( & ip_globals.netifs_lock );
return ENOMEM;
}
route->address.s_addr = address.s_addr;
route->netmask.s_addr = netmask.s_addr;
route->gateway.s_addr = gateway.s_addr;
610,6 → 639,7
route->netif = netif;
index = ip_routes_add( & netif->routes, route );
if( index < 0 ) free( route );
rwlock_write_unlock( & ip_globals.netifs_lock );
return index;
}
 
650,12 → 680,17
int ip_set_gateway_req( int ip_phone, device_id_t device_id, in_addr_t gateway ){
ip_netif_ref netif;
 
rwlock_write_lock( & ip_globals.netifs_lock );
netif = ip_netifs_find( & ip_globals.netifs, device_id );
if( ! netif ) return ENOENT;
if( ! netif ){
rwlock_write_unlock( & ip_globals.netifs_lock );
return ENOENT;
}
ip_globals.gateway.address.s_addr = 0;
ip_globals.gateway.netmask.s_addr = 0;
ip_globals.gateway.gateway.s_addr = gateway.s_addr;
ip_globals.gateway.netif = netif;
rwlock_write_unlock( & ip_globals.netifs_lock );
return EOK;
}
 
708,7 → 743,7
return EPERM;
}
// create the last fragment
new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( address_length > addr_len ) ? address_length : addr_len ));
new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, ((( size_t ) address_length > addr_len ) ? ( size_t ) address_length : addr_len ));
if( ! new_packet ) return ENOMEM;
last_header = ip_create_last_header( new_packet, header );
if( ! last_header ){
864,14 → 899,20
// TODO fragmented
return ENOTSUP;
}else{
ERROR_PROPAGATE( packet_set_addr( packet, ( uint8_t * ) & header->source_address, ( uint8_t * ) & header->destination_address, IP_ADDR ));
rwlock_read_lock( & ip_globals.protos_lock );
proto = ip_protos_find( & ip_globals.protos, header->protocol );
if( ! proto ) return ENOENT;
ERROR_PROPAGATE( packet_set_addr( packet, ( uint8_t * ) & header->source_address, ( uint8_t * ) & header->destination_address, IP_ADDR ));
if( proto->tl_received_msg ){
return proto->tl_received_msg( device_id, packet, SERVICE_IP );
if( ! proto ){
rwlock_read_unlock( & ip_globals.protos_lock );
return ENOENT;
}
if( proto->received_msg ){
ERROR_CODE = proto->received_msg( device_id, packet, SERVICE_IP );
}else{
return tl_received_msg( proto->phone, device_id, packet, proto->service );
ERROR_CODE = tl_received_msg( proto->phone, device_id, packet, proto->service );
}
rwlock_read_unlock( & ip_globals.protos_lock );
return ERROR_CODE;
}
}