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; |
} |
} |
|